比较老的MANGOS的服务端的代码。可以作为参考使用
diff --git a/src/game/Chat.cpp b/src/game/Chat.cppindex 91f1c3c..e6d41f7 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -458,6 +458,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL },
{ "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL },
{ "spell_disabled", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellDisabledCommand, "", NULL }, //禁止某个技能,数据库重载
+ { "player_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPlayerLootTemplateCommand, "", NULL }, //重载玩家掉率
{ NULL, 0, false, NULL, "", NULL }
};
diff --git a/src/game/Chat.h b/src/game/Chat.h
index a5ce6d5..184171d 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -384,6 +384,7 @@ class ChatHandler
bool HandleReloadSpellThreatsCommand(const char* args);
bool HandleReloadSpellPetAurasCommand(const char* args);
bool HandleReloadSpellDisabledCommand(const char* args); //禁止某个技能数据库从载
+ bool HandleReloadPlayerLootTemplateCommand(const char* args); //重载玩家掉率
bool HandleResetAchievementsCommand(const char * args);
bool HandleResetAllCommand(const char * args);
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index f56f721..00494d3 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -164,6 +164,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*)
HandleReloadSpellThreatsCommand("a");
HandleReloadSpellPetAurasCommand("a");
HandleReloadSpellDisabledCommand("a"); //禁止某个技能数据库重载
+ HandleReloadPlayerLootTemplateCommand("a"); //重载玩家掉率
return true;
}
@@ -761,6 +762,17 @@ bool ChatHandler::HandleReloadSpellDisabledCommand(const char* /*arg*/) //
return true;
}
+bool ChatHandler::HandleReloadPlayerLootTemplateCommand(const char* /*arg*/) //重载玩家掉率
+{
+ sLog.outString( "Re-Loading Player Loot Template table...");
+
+ objmgr.LoadPlayerLootTemplate();
+
+ SendGlobalSysMessage("DB table `player_loot_template` reloaded.");
+
+ return true;
+}
+
bool ChatHandler::HandleReloadLocalesAchievementRewardCommand(const char*)
{
sLog.outString( "Re-Loading Locales Achievement Reward Data..." );
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 7ba1c53..6440c6a 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -7004,6 +7004,51 @@ void ObjectMgr::LoadSpellDisabledEntrys() //
sLog.outString( ">> Loaded %u disabled spells from `spell_disabled`", total_count);
}//数据库中禁止某个技能
+void ObjectMgr::LoadPlayerLootTemplate() //重载玩家掉率 ObjectMgr:: 属于ObjectMgr.h的 class ObjectMgr,
+{ //所以UNORDERED_MAP定义在class ObjectMgr内
+ m_Player_Loot_Template.clear();
+ QueryResult *result = WorldDatabase.Query("SELECT entry, itemid, chance FROM player_loot_template");
+
+ uint32 total_count = 0;
+
+ if( !result )
+ {
+ barGoLink bar( 1 );
+ bar.step();
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u player loot template", total_count );
+ return;
+ }
+
+ barGoLink bar( result->GetRowCount() );
+
+ Field* fields;
+ do
+ {
+ PlayerLootTemplate temp; //定义内存
+ bar.step();
+ fields = result->Fetch();
+ uint32 entry = fields[0].GetUInt32();
+ temp.itemid = fields[1].GetUInt32();
+ if(!sItemStore.LookupEntry(temp.itemid))
+ {
+ sLog.outDebug("item entry %u from `player_loot_template` is your custom items.",temp.itemid);
+ //continue;
+ }
+ temp.chance = fields[2].GetUInt32();
+
+ m_Player_Loot_Template[entry] = temp; //把值放到内存
+
+ ++total_count;
+ } while ( result->NextRow() );
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u player loot template from `player_loot_template`", total_count);
+}//重载玩家掉率
+
void ObjectMgr::LoadFishingBaseSkillLevel()
{
mFishingBaseForArea.clear(); // for reload case
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index c351295..738e1d7 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -73,6 +73,14 @@ struct GameTele
typedef UNORDERED_MAP<uint32, GameTele > GameTeleMap;
+struct PlayerLootTemplate //玩家掉落系统
+{
+ uint32 entry;
+ uint32 itemid;
+ //uint32 count;
+ uint32 chance;
+};
+
struct ScriptInfo
{
uint32 id;
@@ -707,6 +715,42 @@ class ObjectMgr
bool IsCreatureSpellDisabled(uint32 spellid) { return (m_DisabledCreatureSpells.count(spellid) != 0); }
bool IsPetSpellDisabled(uint32 spellid) { return (m_DisabledPetSpells.count(spellid) != 0); }
+ void LoadPlayerLootTemplate(); //重载玩家掉率
+ uint32 PlayerLootItemid(uint32 entry)//获得物品ID号(要掉落的物品player_loot_template)
+ {
+ uint32 result=0;
+ PlayerLootTemplateMap::const_iterator itr = m_Player_Loot_Template.find(entry);
+ //SpellDisabledMap::const_iterator itr = m_spell_disabled.find(spellid);
+ if(itr != m_Player_Loot_Template.end())
+ {
+ result=itr->second.itemid;
+ }
+ return result;
+ }
+ /*uint32 PlayerLootCount(uint32 count)
+ {
+ uint32 result=0;
+ PlayerLootTemplateMap::const_iterator itr = m_Player_Loot_Template.find(count);
+ //SpellDisabledMap::const_iterator itr = m_spell_disabled.find(spellid);
+ if(itr != m_Player_Loot_Template.end())
+ {
+ result=itr->second.count;
+ }
+ return result;
+ }*/
+
+ uint32 PlayerLootChance(uint32 chance)//获得物品掉落的几率(player_loot_template)
+ {
+ uint32 result=0;
+ PlayerLootTemplateMap::const_iterator itr = m_Player_Loot_Template.find(chance);
+ //SpellDisabledMap::const_iterator itr = m_spell_disabled.find(spellid);
+ if(itr != m_Player_Loot_Template.end())
+ {
+ result=itr->second.chance;
+ }
+ return result;
+ }
+
int GetIndexForLocale(LocaleConstant loc);
LocaleConstant GetLocaleForIndex(int i);
@@ -835,6 +879,9 @@ class ObjectMgr
std::set<uint32> m_DisabledCreatureSpells; //数据库中禁止某个技能
std::set<uint32> m_DisabledPetSpells;//数据库中禁止某个技能
+ typedef UNORDERED_MAP<uint32, PlayerLootTemplate> PlayerLootTemplateMap;//玩家掉率系统的内存地图定义
+ PlayerLootTemplateMap m_Player_Loot_Template;
+
GraveYardMap mGraveYardMap;
GameTeleMap m_GameTeleMap;
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 97d8a18..95b03e2 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -18726,6 +18726,36 @@ void Player::AddItemDurations( Item *item )
}
}
+//PvP 杀人系统
+void Player::PSendSysCnMessage(int32 entry, ...)//个人信息,左下角,entry对应mangos_string
+{
+ const char *format = GetSession()->GetMangosString(entry);
+ va_list ap;
+ char str [2048];
+ va_start(ap, entry);
+ vsnprintf(str,2048,format, ap );
+ va_end(ap);
+ ChatHandler(this).SendSysMessage(str);
+}
+
+void Player::PSendWorldCnCenterMessage(int32 entry, ...)//全世界信息,屏幕中间entry对应mangos_string
+{
+ char const* format = GetSession()->GetMangosString(entry);
+ if(format)
+ {
+ va_list ap;
+ char szStr [1024];
+ szStr[0] = '\0';
+ va_start(ap, entry);
+ vsnprintf( szStr, 1024, format, ap );
+ va_end(ap);
+
+ WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr)+1));
+ data << szStr;
+ sWorld.SendGlobalMessage(&data);
+ }
+}//PvP 杀人系统
+
void Player::AutoUnequipOffhandIfNeed()
{
Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND );
diff --git a/src/game/Player.h b/src/game/Player.h
index 0782088..cbd9377 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1063,8 +1063,11 @@ class MANGOS_DLL_SPEC Player : public Unit
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
void SetGMVisible(bool on);
void SetPvPDeath(bool on) { if(on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; }
-
- void GiveXP(uint32 xp, Unit* victim);
+//-----------------------------个性化开始-------------------------
+ void PSendSysCnMessage(int32 entry, ...);//个人信息,只有个人能看到 //PvP 杀人系统
+ void PSendWorldCnCenterMessage(int32 entry, ...);//全世界信息,屏幕中间entry对应mangos_string //PvP 杀人系统
+//-----------------------------个性化结束-------------------------
+ void GiveXP(uint32 xp, Unit* victim);
void GiveLevel(uint32 level);
void InitStatsForLevel(bool reapplyMods = false);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index e12b0d8..6f3e7b4 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -561,6 +561,193 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
{
player->RewardPlayerAndGroupAtKill(pVictim);
player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
+
+ // PvP 杀人掉落系统player_loot_template
+ if (player && pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ int8 leveldiff = player->getLevel() - pVictim->getLevel();
+ int8 leveldiff2 = pVictim->getLevel() - player->getLevel();
+ if(!pVictim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT) && leveldiff < sConfig.GetIntDefault("Player.Loot.Level.Diff", 10) && leveldiff2 < sConfig.GetIntDefault("Player.Loot.Level.Diff", 10))
+ {
+ if(sConfig.GetIntDefault("Player.Loot.Enable", 0) == 1 && PLAYERLIMITPASS==sConfig.GetIntDefault("PlayerLimitPass", 0))
+ {
+ uint8 MapRestriction = sConfig.GetIntDefault("Player.MapRestriction", 4);
+ if( MapRestriction == 1 && player->InBattleGround() && !player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) ||
+ MapRestriction == 2 && player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) ||
+ MapRestriction == 3 && player->InBattleGround() ||
+ MapRestriction == 4 )
+ {
+ for (uint32 entry = 1; entry < 10000; ++entry )
+ {
+ if (sConfig.GetIntDefault("Player.Loot.Item.On.Off", 0) == 0)
+ break;
+ uint32 itemCount = 1;
+ uint32 itemID = objmgr.PlayerLootItemid(entry);
+ uint32 chance = objmgr.PlayerLootChance(entry);
+ if (itemID==0)
+ break;
+ ItemPosCountVec dest;
+ //player->GetSession()->SendAreaTriggerMessage("item id is %u,count is %u, chance is %u ",itemID,itemCount,chance);
+ uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemID, itemCount);
+ if( msg != EQUIP_ERR_OK )
+ {
+ player->SendEquipError( msg, NULL, NULL );
+ //return 0;
+ }
+ else
+ {
+ if (((Player*)pVictim)->HasItemCount(itemID, 1))
+ {
+ //if (chance ==0)break;
+ if (chance >0 && chance<=5)
+ {
+ switch ( rand()%20 )
+ {
+ case 0:break;case 1:break;case 2:break; case 3:break;
+ case 4:break;case 5:break;case 6:break; case 7:break;
+ case 8:break;case 9:break;case 10:break; case 11:break;
+ case 13:break;case 14:break;case 15:break; case 16:break;
+ case 17:break;case 18:break;case 19:break;
+ case 12:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ Item* item_1 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ player->SendNewItem(item_1,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ }
+ }
+ if (chance>5 && chance<=10)
+ {
+ switch ( rand()%10 )
+ {
+ case 0:break;case 1:break;case 2:break; case 3:break;
+ case 4:break;case 9:break;case 6:break; case 7:break;
+ case 8:break;
+ case 5:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ Item* item_2 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ player->SendNewItem(item_2,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ }
+ }
+ if (chance>10 && chance<=30)
+ {
+ switch ( rand()%5 )
+ {
+ case 0:break;case 1:break;case 3:break;case 4:break;
+ case 2:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ Item* item_3 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ player->SendNewItem(item_3,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ }
+ }
+ if (chance>30 && chance<=50)
+ {
+ switch ( rand()%3 )
+ {
+ case 0:break;case 2:break;
+ case 1:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ Item* item_4 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ player->SendNewItem(item_4,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ }
+ }
+ if (chance>50 && chance<=80)
+ {
+ switch ( rand()%2 )
+ {
+ case 0:break;
+ case 1:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ Item* item_5 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ player->SendNewItem(item_5,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ }
+ }
+ if (chance>80 && chance<100)
+ {
+ Item* item_6 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ switch ( rand()%3 )
+ {
+ case 3:break;
+ case 0:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ player->SendNewItem(item_6,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ case 2:
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ player->SendNewItem(item_6,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ break;
+ }
+ }
+ if (chance==100)
+ {
+ ((Player*)pVictim)->DestroyItemCount(itemID, itemCount, true);
+ Item* item_7 = player->StoreNewItem( dest, itemID, true, Item::GenerateItemRandomPropertyId(itemID));
+ player->SendNewItem(item_7,itemCount,true,false);
+ //player->PSendSysCnMessage(15011,pVictim->GetName());
+ ((Player*)pVictim)->PSendSysCnMessage(15013,((Player*)pVictim)->GetItemCharName(itemID));//屏幕左下角信息
+ }
+ }
+ //else
+ //{
+ // player->PSendSysCnMessage(15012);//mangos_sting什么也没得到
+ // ((Player*)pVictim)->PSendSysCnMessage(15014);//屏幕左下角信息
+ // }
+ }
+ }//for循环结束
+ uint32 LootMoney = sConfig.GetIntDefault("Player.Loot.Money", 0);
+ if (LootMoney > 0)
+ {
+ if (((Player*)pVictim)->GetMoney() > LootMoney)
+ {
+ ((Player*)pVictim)->ModifyMoney(-int32(LootMoney));
+ player->ModifyMoney(int32(LootMoney));
+ player->PSendSysCnMessage(15011,LootMoney);//mangos_sting什么也没得到
+ ((Player*)pVictim)->PSendSysCnMessage(15012,LootMoney);//屏幕左下角信息
+ }
+ }
+ uint32 LootIntegral = sConfig.GetIntDefault("Player.Loot.Integral", 0);
+ if (LootIntegral > 0)
+ {
+ if (((Player*)pVictim)->GetAccountJf(((Player*)pVictim)->GetSession()->GetAccountId()) > LootIntegral)
+ {
+ uint32 jf_win=player->GetAccountJf(player->GetSession()->GetAccountId());
+ jf_win=jf_win+LootIntegral;
+ uint32 jf_false=((Player*)pVictim)->GetAccountJf(((Player*)pVictim)->GetSession()->GetAccountId());
+ jf_false=jf_false-LootIntegral;
+ //((Player*)pVictim)->m_session->GetPlayer()->SetAccountJf(jf_false,((Player*)pVictim)->GetSession()->GetAccountId());
+ ((Player*)pVictim)->SetAccountJf(jf_false,((Player*)pVictim)->GetSession()->GetAccountId());
+ //player->m_session->GetPlayer()->ModifyMoney(int32(LootMoney));
+ player->SetAccountJf(jf_win,((Player*)pVictim)->GetSession()->GetAccountId());
+ player->PSendSysCnMessage(15015,LootIntegral);//mangos_sting什么也没得到
+ ((Player*)pVictim)->PSendSysCnMessage(15016,LootIntegral);//屏幕左下角信息
+ }
+ }
+ }
+ if (sConfig.GetIntDefault("Player.PvP.Announce.on.off", 0) == 1)
+ {
+ player->PSendWorldCnCenterMessage(15010,((Player*)this)->GetName(),pVictim->GetName());
+ }
+ }
+
+ }
+ }//PVP 杀人掉落系统结束player_loot_template
}
DEBUG_LOG("DealDamageAttackStop");
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 6b6a337..35d99ca 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -1273,6 +1273,9 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Player Corpses..." );
objmgr.LoadCorpses();
+ sLog.outString( "Loading Player Loot Template..." );//玩家掉落系统
+ objmgr.LoadPlayerLootTemplate();
+
sLog.outString( "Loading Loot Tables..." );
sLog.outString();
LoadLootTables();
|