aboutsummaryrefslogtreecommitdiff
path: root/src/game/ObjectMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/ObjectMgr.cpp')
-rw-r--r--src/game/ObjectMgr.cpp180
1 files changed, 120 insertions, 60 deletions
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index cbf445ebc6b..ec300715f86 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -178,6 +178,9 @@ ObjectMgr::~ObjectMgr()
for (CachePlayerInfoMap::iterator itr = m_mPlayerInfoMap.begin(); itr != m_mPlayerInfoMap.end(); ++itr)
delete itr->second;
+ for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
+ delete itr->second;
+
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
itr->second.Clear();
@@ -635,7 +638,7 @@ void ObjectMgr::LoadCreatureTemplates()
// used later for scale
CreatureDisplayInfoEntry const* displayScaleEntry = NULL;
-
+
if (cInfo->DisplayID_A[0])
{
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->DisplayID_A[0]);
@@ -703,6 +706,18 @@ void ObjectMgr::LoadCreatureTemplates()
if (!displayScaleEntry)
sLog.outErrorDb("Creature (Entry: %u) not has any existed display id in DisplayID_A/DisplayID_A2/DisplayID_H/DisplayID_H2", cInfo->Entry);
+ for(int k = 0; k < MAX_KILL_CREDIT; ++k)
+ {
+ if(cInfo->KillCredit[k])
+ {
+ if(!GetCreatureTemplate(cInfo->KillCredit[k]))
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has not existed creature entry in `KillCredit%d` (%u)",cInfo->Entry,k+1,cInfo->KillCredit[k]);
+ const_cast<CreatureInfo*>(cInfo)->KillCredit[k] = 0;
+ }
+ }
+ }
+
if (cInfo->unit_class && ((1 << (cInfo->unit_class-1)) & CLASSMASK_ALL_CREATURES) == 0)
sLog.outErrorDb("Creature (Entry: %u) has invalid unit_class(%u) for creature_template", cInfo->Entry, cInfo->unit_class);
@@ -786,7 +801,7 @@ void ObjectMgr::LoadCreatureTemplates()
const_cast<CreatureInfo*>(cInfo)->scale = 1.0f;
}
- //const_cast<CreatureInfo*>(cInfo)->dmg_multiplier *= Creature::_GetDamageMod(cInfo->rank);
+ const_cast<CreatureInfo*>(cInfo)->dmg_multiplier *= Creature::_GetDamageMod(cInfo->rank);
}
}
@@ -865,17 +880,17 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const*
endAura.effect_idx = 0;
}
-void ObjectMgr::LoadCreatureAddons()
+void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment)
{
- sCreatureInfoAddonStorage.Load();
+ creatureaddons.Load();
- sLog.outString( ">> Loaded %u creature template addons", sCreatureInfoAddonStorage.RecordCount );
+ sLog.outString(">> Loaded %u %s", creatureaddons.RecordCount, comment);
sLog.outString();
// check data correctness and convert 'auras'
- for(uint32 i = 1; i < sCreatureInfoAddonStorage.MaxEntry; ++i)
+ for(uint32 i = 1; i < creatureaddons.MaxEntry; ++i)
{
- CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry<CreatureDataAddon>(i);
+ CreatureDataAddon const* addon = creatureaddons.LookupEntry<CreatureDataAddon>(i);
if(!addon)
continue;
@@ -883,49 +898,41 @@ void ObjectMgr::LoadCreatureAddons()
{
if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount))
{
- sLog.outErrorDb("Creature (Entry %u) have invalid displayInfoId for mount (%u) defined in `creature_template_addon`.",addon->guidOrEntry, addon->mount);
+ sLog.outErrorDb("Creature (%s %u) have invalid displayInfoId for mount (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->mount, creatureaddons.GetTableName());
const_cast<CreatureDataAddon*>(addon)->mount = 0;
}
}
if (!sEmotesStore.LookupEntry(addon->emote))
- sLog.outErrorDb("Creature (Entry %u) have invalid emote (%u) defined in `creature_template_addon`.",addon->guidOrEntry, addon->emote);
+ sLog.outErrorDb("Creature (%s %u) have invalid emote (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->emote, creatureaddons.GetTableName());
- ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), "creature_template_addon", "Entry");
+ /*if (addon->move_flags & (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4))
+ {
+ sLog.outErrorDb("Creature (%s %u) movement flags mask defined in `%s` include forbidden flags (" I32FMT ") that can crash client, cleanup at load.", entryName, addon->guidOrEntry, creatureaddons.GetTableName(), (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4));
+ const_cast<CreatureDataAddon*>(addon)->move_flags &= ~(MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4);
+ }*/
- if(!sCreatureStorage.LookupEntry<CreatureInfo>(addon->guidOrEntry))
- sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `creature_template_addon`",addon->guidOrEntry);
+ ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), creatureaddons.GetTableName(), entryName);
}
+}
- sCreatureDataAddonStorage.Load();
-
- sLog.outString( ">> Loaded %u creature addons", sCreatureDataAddonStorage.RecordCount );
- sLog.outString();
-
- // check data correctness and convert 'auras'
- for(uint32 i = 1; i < sCreatureDataAddonStorage.MaxEntry; ++i)
- {
- CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry<CreatureDataAddon>(i);
- if(!addon)
- continue;
-
- if (addon->mount)
- {
- if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount))
- {
- sLog.outErrorDb("Creature (GUID %u) have invalid displayInfoId for mount (%u) defined in `creature_addon`.",addon->guidOrEntry, addon->mount);
- const_cast<CreatureDataAddon*>(addon)->mount = 0;
- }
- }
+void ObjectMgr::LoadCreatureAddons()
+{
+ LoadCreatureAddons(sCreatureInfoAddonStorage,"Entry","creature template addons");
- if (!sEmotesStore.LookupEntry(addon->emote))
- sLog.outErrorDb("Creature (GUID %u) have invalid emote (%u) defined in `creature_addon`.",addon->guidOrEntry, addon->emote);
+ // check entry ids
+ for(uint32 i = 1; i < sCreatureInfoAddonStorage.MaxEntry; ++i)
+ if(CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry<CreatureDataAddon>(i))
+ if(!sCreatureStorage.LookupEntry<CreatureInfo>(addon->guidOrEntry))
+ sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `%s`",addon->guidOrEntry, sCreatureInfoAddonStorage.GetTableName());
- ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), "creature_addon", "GUIDLow");
+ LoadCreatureAddons(sCreatureDataAddonStorage,"GUID","creature addons");
- if(mCreatureDataMap.find(addon->guidOrEntry)==mCreatureDataMap.end())
- sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry);
- }
+ // check entry ids
+ for(uint32 i = 1; i < sCreatureDataAddonStorage.MaxEntry; ++i)
+ if(CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry<CreatureDataAddon>(i))
+ if(mCreatureDataMap.find(addon->guidOrEntry)==mCreatureDataMap.end())
+ sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry);
}
EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry)
@@ -1533,6 +1540,12 @@ void ObjectMgr::LoadGameobjects()
data.rotation2 = fields[ 9].GetFloat();
data.rotation3 = fields[10].GetFloat();
data.spawntimesecs = fields[11].GetInt32();
+
+ if (data.spawntimesecs==0 && gInfo->IsDespawnAtAction())
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.",guid,data.id);
+ }
+
data.animprogress = fields[12].GetUInt32();
data.ArtKit = 0;
@@ -2035,6 +2048,12 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->Stackable = 1000;
}
+ if(proto->ContainerSlots > MAX_BAG_SIZE)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u).",i,proto->ContainerSlots,MAX_BAG_SIZE);
+ const_cast<ItemPrototype*>(proto)->ContainerSlots = MAX_BAG_SIZE;
+ }
+
if(proto->StatsCount > MAX_ITEM_PROTO_STATS)
{
sLog.outErrorDb("Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).",i,proto->StatsCount,MAX_ITEM_PROTO_STATS);
@@ -2706,8 +2725,8 @@ void ObjectMgr::LoadPlayerInfo()
// Load playercreate actions
{
- // 0 1 2 3 4 5
- QueryResult *result = WorldDatabase.Query("SELECT race, class, button, action, type, misc FROM playercreateinfo_action");
+ // 0 1 2 3 4
+ QueryResult *result = WorldDatabase.Query("SELECT race, class, button, action, type FROM playercreateinfo_action");
uint32 count = 0;
@@ -2742,10 +2761,7 @@ void ObjectMgr::LoadPlayerInfo()
}
PlayerInfo* pInfo = &playerInfo[current_race][current_class];
- pInfo->action[0].push_back(fields[2].GetUInt16());
- pInfo->action[1].push_back(fields[3].GetUInt16());
- pInfo->action[2].push_back(fields[4].GetUInt16());
- pInfo->action[3].push_back(fields[5].GetUInt16());
+ pInfo->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt8(),fields[3].GetUInt32(),fields[4].GetUInt8()));
bar.step();
++count;
@@ -3901,13 +3917,20 @@ void ObjectMgr::LoadQuests()
qinfo->RewSpell = 0; // no spell reward will display for this quest
}
- else if(!SpellMgr::IsSpellValid(spellInfo))
+ if(!SpellMgr::IsSpellValid(spellInfo))
{
- sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is broken, quest can't be done.",
+ sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is broken, quest will not have a spell reward.",
qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell);
qinfo->RewSpell = 0; // no spell reward will display for this quest
}
+ if(GetTalentSpellCost(qinfo->RewSpell))
+ {
+ sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward.",
+ qinfo->GetQuestId(),qinfo->RewSpell,qinfo->RewSpell);
+ qinfo->RewSpell = 0; // no spell reward will display for this quest
+ continue;
+ }
}
if(qinfo->RewSpellCast)
@@ -3921,13 +3944,20 @@ void ObjectMgr::LoadQuests()
qinfo->RewSpellCast = 0; // no spell will be casted on player
}
- else if(!SpellMgr::IsSpellValid(spellInfo))
+ if(!SpellMgr::IsSpellValid(spellInfo))
{
- sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u is broken, quest can't be done.",
+ sLog.outErrorDb("Quest %u has `RewSpellCast` = %u but spell %u is broken, quest will not have a spell reward.",
qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast);
qinfo->RewSpellCast = 0; // no spell will be casted on player
}
+ if(GetTalentSpellCost(qinfo->RewSpellCast))
+ {
+ sLog.outErrorDb("Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward.",
+ qinfo->GetQuestId(),qinfo->RewSpellCast,qinfo->RewSpellCast);
+ qinfo->RewSpellCast = 0; // no spell will be casted on player
+ continue;
+ }
}
if(qinfo->RewMailTemplateId)
@@ -6131,6 +6161,16 @@ inline void CheckGONoDamageImmuneId(GameObjectInfo const* goInfo,uint32 dataN,ui
goInfo->id,goInfo->type,N,dataN);
}
+inline void CheckGOConsumable(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ // 0/1 correct values
+ if (dataN <= 1)
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) consumable field value.",
+ goInfo->id,goInfo->type,N,dataN);
+}
+
void ObjectMgr::LoadGameobjectInfo()
{
SQLGameObjectLoader loader;
@@ -6173,6 +6213,8 @@ void ObjectMgr::LoadGameobjectInfo()
if (goInfo->chest.lockId)
CheckGOLockId(goInfo,goInfo->chest.lockId,0);
+ CheckGOConsumable(goInfo,goInfo->chest.consumable,3);
+
if (goInfo->chest.linkedTrapId) // linked trap
CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7);
break;
@@ -6208,6 +6250,8 @@ void ObjectMgr::LoadGameobjectInfo()
if (goInfo->goober.lockId)
CheckGOLockId(goInfo,goInfo->goober.lockId,0);
+ CheckGOConsumable(goInfo,goInfo->goober.consumable,3);
+
if (goInfo->goober.pageId) // pageId
{
if (!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
@@ -7054,18 +7098,24 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo
return false;
}
-bool ObjectMgr::IsValidName( const std::string& name, bool create )
+uint8 ObjectMgr::CheckPlayerName( const std::string& name, bool create )
{
std::wstring wname;
if(!Utf8toWStr(name,wname))
- return false;
+ return CHAR_NAME_INVALID_CHARACTER;
- if(wname.size() < 1 || wname.size() > MAX_PLAYER_NAME)
- return false;
+ if(wname.size() > MAX_PLAYER_NAME)
+ return CHAR_NAME_TOO_LONG;
+
+ uint32 minName = sWorld.getConfig(CONFIG_MIN_PLAYER_NAME);
+ if(wname.size() < minName)
+ return CHAR_NAME_TOO_SHORT;
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PLAYER_NAMES);
+ if(!isValidString(wname,strictMask,false,create))
+ return CHAR_NAME_MIXED_LANGUAGES;
- return isValidString(wname,strictMask,false,create);
+ return CHAR_NAME_SUCCESS;
}
bool ObjectMgr::IsValidCharterName( const std::string& name )
@@ -7074,7 +7124,11 @@ bool ObjectMgr::IsValidCharterName( const std::string& name )
if(!Utf8toWStr(name,wname))
return false;
- if(wname.size() < 1)
+ if(wname.size() > MAX_CHARTER_NAME)
+ return false;
+
+ uint32 minName = sWorld.getConfig(CONFIG_MIN_CHARTER_NAME);
+ if(wname.size() < minName)
return false;
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_CHARTER_NAMES);
@@ -7082,18 +7136,24 @@ bool ObjectMgr::IsValidCharterName( const std::string& name )
return isValidString(wname,strictMask,true);
}
-bool ObjectMgr::IsValidPetName( const std::string& name )
+PetNameInvalidReason ObjectMgr::CheckPetName( const std::string& name )
{
std::wstring wname;
if(!Utf8toWStr(name,wname))
- return false;
+ return PET_NAME_INVALID;
- if(wname.size() < 1)
- return false;
+ if(wname.size() > MAX_PET_NAME)
+ return PET_NAME_TOO_LONG;
+
+ uint32 minName = sWorld.getConfig(CONFIG_MIN_PET_NAME);
+ if(wname.size() < minName)
+ return PET_NAME_TOO_SHORT;
uint32 strictMask = sWorld.getConfig(CONFIG_STRICT_PET_NAMES);
+ if(!isValidString(wname,strictMask,false))
+ return PET_NAME_MIXED_LANGUAGES;
- return isValidString(wname,strictMask,false);
+ return PET_NAME_SUCCESS;
}
int ObjectMgr::GetIndexForLocale( LocaleConstant loc )
@@ -7158,7 +7218,7 @@ void ObjectMgr::LoadGameObjectForQuests()
// scan GO chest with loot including quest items
case GAMEOBJECT_TYPE_CHEST:
{
- uint32 loot_id = GameObject::GetLootId(goInfo);
+ uint32 loot_id = goInfo->GetLootId();
// find quest loot for GO
if(LootTemplates_Gameobject.HaveQuestLootFor(loot_id))