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.cpp1769
1 files changed, 1228 insertions, 541 deletions
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 227b0f90f28..8f87e58ed26 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,14 +30,13 @@
#include "SpellMgr.h"
#include "UpdateMask.h"
#include "World.h"
-#include "WorldSession.h"
#include "Group.h"
#include "Guild.h"
#include "ArenaTeam.h"
#include "Transports.h"
#include "ProgressBar.h"
#include "Language.h"
-#include "GameEvent.h"
+#include "GameEventMgr.h"
#include "Spell.h"
#include "Chat.h"
#include "AccountMgr.h"
@@ -116,6 +115,7 @@ ObjectMgr::ObjectMgr()
m_hiCharGuid = 1;
m_hiCreatureGuid = 1;
m_hiPetGuid = 1;
+ m_hiVehicleGuid = 1;
m_hiItemGuid = 1;
m_hiGoGuid = 1;
m_hiDoGuid = 1;
@@ -127,14 +127,6 @@ ObjectMgr::ObjectMgr()
m_arenaTeamId = 1;
m_auctionid = 1;
- mGuildBankTabPrice.resize(GUILD_BANK_MAX_TABS);
- mGuildBankTabPrice[0] = 100;
- mGuildBankTabPrice[1] = 250;
- mGuildBankTabPrice[2] = 500;
- mGuildBankTabPrice[3] = 1000;
- mGuildBankTabPrice[4] = 2500;
- mGuildBankTabPrice[5] = 5000;
-
// Only zero condition left, others will be added while loading DB tables
mConditions.resize(1);
}
@@ -142,24 +134,10 @@ ObjectMgr::ObjectMgr()
ObjectMgr::~ObjectMgr()
{
for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++i )
- {
delete i->second;
- }
- mQuestTemplates.clear( );
-
- for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++i )
- {
- delete i->second;
- }
- mGossipText.clear( );
-
- mAreaTriggers.clear();
for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++i )
- {
delete[] i->second;
- }
- petInfo.clear();
// free only if loaded
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
@@ -189,7 +167,7 @@ ObjectMgr::~ObjectMgr()
void ObjectMgr::LoadPlayerInfoInCache()
{
- QueryResult *result = CharacterDatabase.PQuery("SELECT guid, name, data, class FROM characters");
+ QueryResult *result = CharacterDatabase.PQuery("SELECT guid, name, data, class FROM characters");
if(!result)
{
sLog.outError( "Loading Player Cache failed.");
@@ -251,7 +229,7 @@ Group * ObjectMgr::GetGroupByLeader(const uint64 &guid) const
return NULL;
}
-Guild * ObjectMgr::GetGuildById(const uint32 GuildId) const
+Guild * ObjectMgr::GetGuildById(uint32 GuildId) const
{
GuildMap::const_iterator itr = mGuildMap.find(GuildId);
if (itr != mGuildMap.end())
@@ -269,7 +247,7 @@ Guild * ObjectMgr::GetGuildByName(const std::string& guildname) const
return NULL;
}
-std::string ObjectMgr::GetGuildNameById(const uint32 GuildId) const
+std::string ObjectMgr::GetGuildNameById(uint32 GuildId) const
{
GuildMap::const_iterator itr = mGuildMap.find(GuildId);
if (itr != mGuildMap.end())
@@ -296,7 +274,8 @@ void ObjectMgr::RemoveGuild(uint32 Id)
{
mGuildMap.erase(Id);
}
-ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 arenateamid) const
+
+ArenaTeam* ObjectMgr::GetArenaTeamById(uint32 arenateamid) const
{
ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid);
if (itr != mArenaTeamMap.end())
@@ -350,7 +329,7 @@ void ObjectMgr::LoadCreatureLocales()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outString(">> Loaded 0 creature locale strings. DB table `locales_creature` is empty.");
return;
}
@@ -398,7 +377,7 @@ void ObjectMgr::LoadCreatureLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() );
+ sLog.outString( ">> Loaded %lu creature locale strings", (unsigned long)mCreatureLocaleMap.size() );
}
void ObjectMgr::LoadNpcOptionLocales()
@@ -418,7 +397,7 @@ void ObjectMgr::LoadNpcOptionLocales()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outString(">> Loaded 0 npc_option locale strings. DB table `locales_npc_option` is empty.");
return;
}
@@ -466,13 +445,64 @@ void ObjectMgr::LoadNpcOptionLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u npc_option locale strings", mNpcOptionLocaleMap.size() );
+ sLog.outString( ">> Loaded %lu npc_option locale strings", (unsigned long)mNpcOptionLocaleMap.size() );
+}
+
+void ObjectMgr::LoadPointOfInterestLocales()
+{
+ mPointOfInterestLocaleMap.clear(); // need for reload case
+
+ QueryResult *result = WorldDatabase.Query("SELECT entry,icon_name_loc1,icon_name_loc2,icon_name_loc3,icon_name_loc4,icon_name_loc5,icon_name_loc6,icon_name_loc7,icon_name_loc8 FROM locales_points_of_interest");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString();
+ sLog.outString(">> Loaded 0 points_of_interest locale strings. DB table `locales_points_of_interest` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+
+ uint32 entry = fields[0].GetUInt32();
+
+ PointOfInterestLocale& data = mPointOfInterestLocaleMap[entry];
+
+ for(int i = 1; i < MAX_LOCALE; ++i)
+ {
+ std::string str = fields[i].GetCppString();
+ if(str.empty())
+ continue;
+
+ int idx = GetOrNewIndexForLocale(LocaleConstant(i));
+ if(idx >= 0)
+ {
+ if(data.IconName.size() <= idx)
+ data.IconName.resize(idx+1);
+
+ data.IconName[idx] = str;
+ }
+ }
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %lu points_of_interest locale strings", (unsigned long)mPointOfInterestLocaleMap.size() );
}
struct SQLCreatureLoader : public SQLStorageLoaderBase<SQLCreatureLoader>
{
template<class D>
- void convert_from_str(uint32 field_pos, char *src, D &dst)
+ void convert_from_str(uint32 /*field_pos*/, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
@@ -523,21 +553,27 @@ void ObjectMgr::LoadCreatureTemplates()
continue;
}
+ if(cInfo->unit_class != heroicInfo->unit_class)
+ {
+ sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in heroic mode (Entry: %u, class %u).",i, cInfo->unit_class, cInfo->HeroicEntry, heroicInfo->unit_class);
+ continue;
+ }
+
if(cInfo->npcflag != heroicInfo->npcflag)
{
sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `npcflag` in heroic mode.",i);
continue;
}
- if(cInfo->classNum != heroicInfo->classNum)
+ if(cInfo->trainer_class != heroicInfo->trainer_class)
{
- sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `classNum` in heroic mode.",i);
+ sLog.outErrorDb("Creature (Entry: %u) has different `trainer_class` in heroic mode (Entry: %u).",i,cInfo->HeroicEntry);
continue;
}
- if(cInfo->race != heroicInfo->race)
+ if(cInfo->trainer_race != heroicInfo->trainer_race)
{
- sLog.outErrorDb("Creature (Entry: %u) listed in `creature_template_substitution` has different `race` in heroic mode.",i);
+ sLog.outErrorDb("Creature (Entry: %u) has different `trainer_race` in heroic mode (Entry: %u).",i,cInfo->HeroicEntry);
continue;
}
@@ -553,6 +589,18 @@ void ObjectMgr::LoadCreatureTemplates()
continue;
}
+ if(heroicInfo->AIName && *heroicInfo->AIName)
+ {
+ sLog.outErrorDb("Heroic mode creature (Entry: %u) has `AIName`, but in any case will used normal mode creature (Entry: %u) AIName.",cInfo->HeroicEntry,i);
+ continue;
+ }
+
+ if(heroicInfo->ScriptID)
+ {
+ sLog.outErrorDb("Heroic mode creature (Entry: %u) has `ScriptName`, but in any case will used normal mode creature (Entry: %u) ScriptName.",cInfo->HeroicEntry,i);
+ continue;
+ }
+
hasHeroicEntries.insert(i);
heroicEntries.insert(cInfo->HeroicEntry);
}
@@ -587,6 +635,9 @@ void ObjectMgr::LoadCreatureTemplates()
const_cast<CreatureInfo*>(cInfo)->Modelid_H2 = 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);
+
if(cInfo->dmgschool >= MAX_SPELL_SCHOOL)
{
sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`",cInfo->Entry,cInfo->dmgschool);
@@ -602,6 +653,19 @@ void ObjectMgr::LoadCreatureTemplates()
if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE)
sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type);
+ if(cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type))
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`",cInfo->Entry,cInfo->type);
+ const_cast<CreatureInfo*>(cInfo)->type = CREATURE_TYPE_HUMANOID;
+ }
+
+ // must exist or used hidden but used in data horse case
+ if(cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM )
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`",cInfo->Entry,cInfo->family);
+ const_cast<CreatureInfo*>(cInfo)->family = 0;
+ }
+
if(cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE)
{
sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType);
@@ -615,6 +679,15 @@ void ObjectMgr::LoadCreatureTemplates()
sLog.outErrorDb("Creature (Entry: %u) has non-existing PetSpellDataId (%u)", cInfo->Entry, cInfo->PetSpellDataId);
}
+ for(int j = 0; j < CREATURE_MAX_SPELLS; ++j)
+ {
+ if(cInfo->spells[j] && !sSpellStore.LookupEntry(cInfo->spells[j]))
+ {
+ sLog.outErrorDb("Creature (Entry: %u) has non-existing Spell%d (%u), set to 0", cInfo->Entry, j+1,cInfo->spells[j]);
+ const_cast<CreatureInfo*>(cInfo)->spells[j] = 0;
+ }
+ }
+
if(cInfo->MovementType >= MAX_DB_MOTION_TYPE)
{
sLog.outErrorDb("Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE.",cInfo->Entry,cInfo->MovementType);
@@ -729,6 +802,15 @@ void ObjectMgr::LoadCreatureAddons()
if(!addon)
continue;
+ if (addon->mount)
+ {
+ 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);
+ }
+
+ if (!sEmotesStore.LookupEntry(addon->emote))
+ sLog.outErrorDb("Creature (Entry %u) have invalid emote (%u) defined in `creature_template_addon`.",addon->guidOrEntry, addon->emote);
+
ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), "creature_template_addon", "Entry");
if(!sCreatureStorage.LookupEntry<CreatureInfo>(addon->guidOrEntry))
@@ -747,6 +829,15 @@ void ObjectMgr::LoadCreatureAddons()
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);
+ }
+
+ if (!sEmotesStore.LookupEntry(addon->emote))
+ sLog.outErrorDb("Creature (GUID %u) have invalid emote (%u) defined in `creature_addon`.",addon->guidOrEntry, addon->emote);
+
ConvertCreatureAddonAuras(const_cast<CreatureDataAddon*>(addon), "creature_addon", "GUIDLow");
if(mCreatureDataMap.find(addon->guidOrEntry)==mCreatureDataMap.end())
@@ -763,6 +854,42 @@ void ObjectMgr::LoadEquipmentTemplates()
{
sEquipmentStorage.Load();
+ for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i)
+ {
+ EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry<EquipmentInfo>(i);
+
+ if(!eqInfo)
+ continue;
+
+ for(uint8 j=0; j<3; j++)
+ {
+ if(!eqInfo->equipentry[j])
+ continue;
+
+ ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]);
+
+ if(!dbcitem)
+ {
+ sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i);
+ const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;
+ continue;
+ }
+
+ if(dbcitem->InventoryType != INVTYPE_WEAPON &&
+ dbcitem->InventoryType != INVTYPE_SHIELD &&
+ dbcitem->InventoryType != INVTYPE_RANGED &&
+ dbcitem->InventoryType != INVTYPE_2HWEAPON &&
+ dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND &&
+ dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND &&
+ dbcitem->InventoryType != INVTYPE_HOLDABLE &&
+ dbcitem->InventoryType != INVTYPE_THROWN &&
+ dbcitem->InventoryType != INVTYPE_RANGEDRIGHT)
+ {
+ sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i);
+ const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;
+ }
+ }
+ }
sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount );
sLog.outString();
}
@@ -780,7 +907,9 @@ uint32 ObjectMgr::ChooseDisplayId(uint32 team, const CreatureInfo *cinfo, const
if (!data || data->displayid == 0) // use defaults from the template
{
display_id = cinfo->GetRandomValidModelId();
- } else display_id = data->displayid; // overwritten from creature data
+ }
+ else
+ display_id = data->displayid; // overwritten from creature data
return display_id;
}
@@ -924,9 +1053,10 @@ void ObjectMgr::LoadCreatures()
QueryResult *result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid,"
// 4 5 6 7 8 9 10 11
"equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint,"
- // 12 13 14 15 16 17
- "curhealth, curmana, DeathState, MovementType, spawnMask, event "
- "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid");
+ // 12 13 14 15 16 17 18 19
+ "curhealth, curmana, DeathState, MovementType, spawnMask, phaseMask, event, pool_entry "
+ "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid "
+ "LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid");
if(!result)
{
@@ -934,7 +1064,7 @@ void ObjectMgr::LoadCreatures()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outErrorDb(">> Loaded 0 creature. DB table `creature` is empty.");
return;
}
@@ -946,6 +1076,9 @@ void ObjectMgr::LoadCreatures()
if(cInfo->HeroicEntry)
heroicCreatures.insert(cInfo->HeroicEntry);
+ //TODO: remove this
+ //gameeventmgr.mGameEventCreatureGuids.resize(52*2-1);
+
barGoLink bar(result->GetRowCount());
do
@@ -953,11 +1086,19 @@ void ObjectMgr::LoadCreatures()
Field *fields = result->Fetch();
bar.step();
- uint32 guid = fields[0].GetUInt32();
+ uint32 guid = fields[ 0].GetUInt32();
+ uint32 entry = fields[ 1].GetUInt32();
+
+ CreatureInfo const* cInfo = GetCreatureTemplate(entry);
+ if(!cInfo)
+ {
+ sLog.outErrorDb("Table `creature` has creature (GUID: %u) with non existing creature entry %u, skipped.", guid, entry);
+ continue;
+ }
CreatureData& data = mCreatureDataMap[guid];
- data.id = fields[ 1].GetUInt32();
+ data.id = entry;
data.mapid = fields[ 2].GetUInt32();
data.displayid = fields[ 3].GetUInt32();
data.equipmentId = fields[ 4].GetUInt32();
@@ -973,20 +1114,25 @@ void ObjectMgr::LoadCreatures()
data.is_dead = fields[14].GetBool();
data.movementType = fields[15].GetUInt8();
data.spawnMask = fields[16].GetUInt8();
- int16 gameEvent = fields[17].GetInt16();
+ data.phaseMask = fields[17].GetUInt16();
+ int16 gameEvent = fields[18].GetInt16();
+ int16 PoolId = fields[19].GetInt16();
- CreatureInfo const* cInfo = GetCreatureTemplate(data.id);
- if(!cInfo)
+ if(heroicCreatures.find(data.id)!=heroicCreatures.end())
{
- sLog.outErrorDb("Table `creature` have creature (GUID: %u) with not existed creature entry %u, skipped.",guid,data.id );
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as heroic template in `creature_template_substitution`, skipped.",guid,data.id );
continue;
}
- if(heroicCreatures.find(data.id)!=heroicCreatures.end())
+ // I do not know why but in db most display id are not zero
+ /*if(data.displayid == 11686 || data.displayid == 24719)
{
- sLog.outErrorDb("Table `creature` have creature (GUID: %u) that listed as heroic template in `creature_template_substitution`, skipped.",guid,data.id );
- continue;
+ (const_cast<CreatureInfo*>(cInfo))->flags_extra |= CREATURE_FLAG_EXTRA_TRIGGER;
}
+ else if(data.displayid == cInfo->Modelid_A1 || data.displayid == cInfo->Modelid_A2
+ || data.displayid == cInfo->Modelid_H1 || data.displayid == cInfo->Modelid_H2)
+ data.displayid = 0;
+ */
if(data.equipmentId > 0) // -1 no equipment, 0 use default
{
@@ -1003,6 +1149,13 @@ void ObjectMgr::LoadCreatures()
data.curhealth = cInfo->minhealth;
}
+ if(cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
+ {
+ MapEntry const* map = sMapStore.LookupEntry(data.mapid);
+ if(!map || !map->IsDungeon())
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance.",guid,data.id);
+ }
+
if(data.curmana < cInfo->minmana)
{
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with low current mana (%u), `creature_template`.`minmana`=%u.",guid,data.id,data.curmana, cInfo->minmana );
@@ -1021,6 +1174,8 @@ void ObjectMgr::LoadCreatures()
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=1 (random movement) but with `spawndist`=0, replace by idle movement type (0).",guid,data.id );
data.movementType = IDLE_MOTION_TYPE;
}
+ else if(cInfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
+ data.movementType = IDLE_MOTION_TYPE;
}
else if(data.movementType == IDLE_MOTION_TYPE)
{
@@ -1031,8 +1186,29 @@ void ObjectMgr::LoadCreatures()
}
}
- if (gameEvent==0) // if not this is to be managed by GameEvent System
+ if(data.phaseMask==0)
+ {
+ sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id );
+ data.phaseMask = 1;
+ }
+
+ //if(entry == 32307 || entry == 32308)
+ /*if(entry == 30739 || entry == 30740)
+ {
+ gameEvent = 51;
+ uint32 guid2 = objmgr.GenerateLowGuid(HIGHGUID_UNIT);
+ CreatureData& data2 = mCreatureDataMap[guid2];
+ data2 = data;
+// data2.id = (entry == 32307 ? 32308 : 32307);
+ data2.id = (entry == 30739 ? 30740 : 30739);
+ data2.displayid = 0;
+ gameeventmgr.mGameEventCreatureGuids[51+51].push_back(guid);
+ gameeventmgr.mGameEventCreatureGuids[51+50].push_back(guid2);
+ }*/
+
+ if (gameEvent==0 && PoolId==0) // if not this is to be managed by GameEvent System or Pool system
AddCreatureToGrid(guid, &data);
+
++count;
} while (result->NextRow());
@@ -1040,7 +1216,7 @@ void ObjectMgr::LoadCreatures()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u creatures", mCreatureDataMap.size() );
+ sLog.outString( ">> Loaded %lu creatures", (unsigned long)mCreatureDataMap.size() );
}
void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data)
@@ -1075,15 +1251,112 @@ void ObjectMgr::RemoveCreatureFromGrid(uint32 guid, CreatureData const* data)
}
}
+uint32 ObjectMgr::AddGameObject(uint32 entry, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay, float rotation0, float rotation1, float rotation2, float rotation3)
+{
+ GameObjectInfo const* goinfo = GetGameObjectInfo(entry);
+ if (!goinfo)
+ return 0;
+
+ uint32 guid = GenerateLowGuid(HIGHGUID_GAMEOBJECT);
+ GameObjectData& data = NewGOData(guid);
+ data.id = entry;
+ data.mapid = mapId;
+ data.posX = x;
+ data.posY = y;
+ data.posZ = z;
+ data.orientation = o;
+ data.rotation0 = rotation0;
+ data.rotation1 = rotation1;
+ data.rotation2 = rotation2;
+ data.rotation3 = rotation3;
+ data.spawntimesecs = spawntimedelay;
+ data.animprogress = 100;
+ data.spawnMask = 1;
+ data.go_state = GO_STATE_READY;
+ data.phaseMask = PHASEMASK_NORMAL;
+ data.dbData = false;
+
+ AddGameobjectToGrid(guid, &data);
+
+ // Spawn if necessary (loaded grids only)
+ if(Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(mapId)))
+ {
+ // We use spawn coords to spawn
+ if(!map->Instanceable() && !map->IsRemovalGrid(x, y))
+ {
+ GameObject *go = new GameObject;
+ if(!go->LoadFromDB(guid, map))
+ {
+ sLog.outError("AddGameObject: cannot add gameobject entry %u to map", entry);
+ delete go;
+ return 0;
+ }
+ map->Add(go);
+ }
+ }
+
+ return guid;
+}
+
+uint32 ObjectMgr::AddCreature(uint32 entry, uint32 team, uint32 mapId, float x, float y, float z, float o, uint32 spawntimedelay)
+{
+ CreatureInfo const *cInfo = GetCreatureTemplate(entry);
+ if(!cInfo)
+ return 0;
+
+ uint32 guid = GenerateLowGuid(HIGHGUID_UNIT);
+ CreatureData& data = NewOrExistCreatureData(guid);
+ data.id = entry;
+ data.mapid = mapId;
+ data.displayid = 0;
+ data.equipmentId = cInfo->equipmentId;
+ data.posX = x;
+ data.posY = y;
+ data.posZ = z;
+ data.orientation = o;
+ data.spawntimesecs = spawntimedelay;
+ data.spawndist = 0;
+ data.currentwaypoint = 0;
+ data.curhealth = cInfo->maxhealth;
+ data.curmana = cInfo->maxmana;
+ data.is_dead = false;
+ data.movementType = cInfo->MovementType;
+ data.spawnMask = 1;
+ data.phaseMask = PHASEMASK_NORMAL;
+ data.dbData = false;
+
+ AddCreatureToGrid(guid, &data);
+
+ // Spawn if necessary (loaded grids only)
+ if(Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(mapId)))
+ {
+ // We use spawn coords to spawn
+ if(!map->Instanceable() && !map->IsRemovalGrid(x, y))
+ {
+ Creature* creature = new Creature;
+ if(!creature->LoadFromDB(guid, map))
+ {
+ sLog.outError("AddCreature: cannot add creature entry %u to map", entry);
+ delete creature;
+ return 0;
+ }
+ map->Add(creature);
+ }
+ }
+
+ return guid;
+}
+
void ObjectMgr::LoadGameobjects()
{
uint32 count = 0;
// 0 1 2 3 4 5 6
QueryResult *result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation,"
- // 7 8 9 10 11 12 13 14 15
- "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, event "
- "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid");
+ // 7 8 9 10 11 12 13 14 15 16 17
+ "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, event, pool_entry "
+ "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid "
+ "LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid");
if(!result)
{
@@ -1103,11 +1376,19 @@ void ObjectMgr::LoadGameobjects()
Field *fields = result->Fetch();
bar.step();
- uint32 guid = fields[0].GetUInt32();
+ uint32 guid = fields[ 0].GetUInt32();
+ uint32 entry = fields[ 1].GetUInt32();
+
+ GameObjectInfo const* gInfo = GetGameObjectInfo(entry);
+ if(!gInfo)
+ {
+ sLog.outErrorDb("Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped.", guid, entry);
+ continue;
+ }
GameObjectData& data = mGameObjectDataMap[guid];
- data.id = fields[ 1].GetUInt32();
+ data.id = entry;
data.mapid = fields[ 2].GetUInt32();
data.posX = fields[ 3].GetFloat();
data.posY = fields[ 4].GetFloat();
@@ -1119,19 +1400,46 @@ void ObjectMgr::LoadGameobjects()
data.rotation3 = fields[10].GetFloat();
data.spawntimesecs = fields[11].GetInt32();
data.animprogress = fields[12].GetUInt32();
- data.go_state = fields[13].GetUInt32();
data.ArtKit = 0;
+
+ uint32 go_state = fields[13].GetUInt32();
+ if (go_state >= MAX_GO_STATE)
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid `state` (%u) value, skip",guid,data.id,go_state);
+ continue;
+ }
+ data.go_state = GOState(go_state);
+
data.spawnMask = fields[14].GetUInt8();
- int16 gameEvent = fields[15].GetInt16();
+ data.phaseMask = fields[15].GetUInt16();
+ int16 gameEvent = fields[16].GetInt16();
+ int16 PoolId = fields[17].GetInt16();
- GameObjectInfo const* gInfo = GetGameObjectInfo(data.id);
- if(!gInfo)
+ if(data.rotation2 < -1.0f || data.rotation2 > 1.0f)
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip",guid,data.id,data.rotation2 );
+ continue;
+ }
+
+ if(data.rotation3 < -1.0f || data.rotation3 > 1.0f)
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip",guid,data.id,data.rotation3 );
+ continue;
+ }
+
+ if(!MapManager::IsValidMapCoord(data.mapid,data.posX,data.posY,data.posZ,data.orientation))
{
- sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u) with not existed gameobject entry %u, skipped.",guid,data.id );
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid coordinates, skip",guid,data.id );
continue;
}
- if (gameEvent==0) // if not this is to be managed by GameEvent System
+ if(data.phaseMask==0)
+ {
+ sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id );
+ data.phaseMask = 1;
+ }
+
+ if (gameEvent==0 && PoolId==0) // if not this is to be managed by GameEvent System or Pool system
AddGameobjectToGrid(guid, &data);
++count;
@@ -1140,7 +1448,7 @@ void ObjectMgr::LoadGameobjects()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u gameobjects", mGameObjectDataMap.size());
+ sLog.outString( ">> Loaded %lu gameobjects", (unsigned long)mGameObjectDataMap.size());
}
void ObjectMgr::AddGameobjectToGrid(uint32 guid, GameObjectData const* data)
@@ -1210,7 +1518,7 @@ void ObjectMgr::LoadCreatureRespawnTimes()
delete result;
- sLog.outString( ">> Loaded %u creature respawn times", mCreatureRespawnTimes.size() );
+ sLog.outString( ">> Loaded %lu creature respawn times", (unsigned long)mCreatureRespawnTimes.size() );
sLog.outString();
}
@@ -1252,7 +1560,7 @@ void ObjectMgr::LoadGameobjectRespawnTimes()
delete result;
- sLog.outString( ">> Loaded %u gameobject respawn times", mGORespawnTimes.size() );
+ sLog.outString( ">> Loaded %lu gameobject respawn times", (unsigned long)mGORespawnTimes.size() );
sLog.outString();
}
@@ -1355,7 +1663,7 @@ void ObjectMgr::LoadItemLocales()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outString(">> Loaded 0 Item locale strings. DB table `locales_item` is empty.");
return;
}
@@ -1404,13 +1712,13 @@ void ObjectMgr::LoadItemLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u Item locale strings", mItemLocaleMap.size() );
+ sLog.outString( ">> Loaded %lu Item locale strings", (unsigned long)mItemLocaleMap.size() );
}
struct SQLItemLoader : public SQLStorageLoaderBase<SQLItemLoader>
{
template<class D>
- void convert_from_str(uint32 field_pos, char *src, D &dst)
+ void convert_from_str(uint32 /*field_pos*/, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
@@ -1439,6 +1747,32 @@ void ObjectMgr::LoadItemPrototypes()
if(dbcitem)
{
+ if(proto->Class != dbcitem->Class)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct class %u, must be %u (still using DB value).",i,proto->Class,dbcitem->Class);
+ // It safe let use Class from DB
+ }
+ /* disabled: have some strange wrong cases for Subclass values.
+ for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[]
+ if(proto->SubClass != dbcitem->SubClass)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass);
+ // It safe let use Subclass from DB
+ }
+ */
+
+ if(proto->Unk0 != dbcitem->Unk0)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value).",i,proto->Unk0,dbcitem->Unk0);
+ // It safe let use Unk0 from DB
+ }
+
+ if(proto->Material != dbcitem->Material)
+ {
+ sLog.outErrorDb("Item (Entry: %u) not correct %i material, must be %i (still using DB value).",i,proto->Material,dbcitem->Material);
+ // It safe let use Material from DB
+ }
+
if(proto->InventoryType != dbcitem->InventoryType)
{
sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType);
@@ -1464,7 +1798,7 @@ void ObjectMgr::LoadItemPrototypes()
if(proto->Class >= MAX_ITEM_CLASS)
{
sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class);
- const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_JUNK;
+ const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_MISC;
}
if(proto->SubClass >= MaxItemSubclassValues[proto->Class])
@@ -1497,14 +1831,30 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->RequiredSkill = 0;
}
- if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE))
{
- sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped.",i,proto->AllowableClass);
- }
- if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE))
- {
- sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped.",i,proto->AllowableRace);
+ // can be used in equip slot, as page read use in inventory, or spell casting at use
+ bool req = proto->InventoryType!=INVTYPE_NON_EQUIP || proto->PageText;
+ if(!req)
+ {
+ for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
+ {
+ if(proto->Spells[j].SpellId)
+ {
+ req = true;
+ break;
+ }
+ }
+ }
+
+ if(req)
+ {
+ if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE))
+ sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use.",i,proto->AllowableClass);
+
+ if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE))
+ sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use.",i,proto->AllowableRace);
+ }
}
if(proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell))
@@ -1530,18 +1880,35 @@ void ObjectMgr::LoadItemPrototypes()
else if(proto->RequiredReputationRank > MIN_REPUTATION_RANK)
sLog.outErrorDb("Item (Entry: %u) has RequiredReputationFaction ==0 but RequiredReputationRank > 0, rank setting is useless.",i);
+ if(proto->MaxCount < -1)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.",i,proto->MaxCount);
+ const_cast<ItemPrototype*>(proto)->MaxCount = -1;
+ }
+
if(proto->Stackable==0)
{
- sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%u), replace by default 1.",i,proto->Stackable);
+ sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.",i,proto->Stackable);
const_cast<ItemPrototype*>(proto)->Stackable = 1;
}
+ else if(proto->Stackable < -1)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.",i,proto->Stackable);
+ const_cast<ItemPrototype*>(proto)->Stackable = -1;
+ }
else if(proto->Stackable > 255)
{
sLog.outErrorDb("Item (Entry: %u) has too large value in stackable (%u), replace by hardcoded upper limit (255).",i,proto->Stackable);
const_cast<ItemPrototype*>(proto)->Stackable = 255;
}
- for (int j = 0; j < 10; j++)
+ 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);
+ const_cast<ItemPrototype*>(proto)->StatsCount = MAX_ITEM_PROTO_STATS;
+ }
+
+ for (int j = 0; j < MAX_ITEM_PROTO_STATS; ++j)
{
// for ItemStatValue != 0
if(proto->ItemStat[j].ItemStatValue && proto->ItemStat[j].ItemStatType >= MAX_ITEM_MOD)
@@ -1551,7 +1918,7 @@ void ObjectMgr::LoadItemPrototypes()
}
}
- for (int j = 0; j < 5; j++)
+ for (int j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j)
{
if(proto->Damage[j].DamageType >= MAX_SPELL_SCHOOL)
{
@@ -1561,7 +1928,7 @@ void ObjectMgr::LoadItemPrototypes()
}
// special format
- if(proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN)
+ if((proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) || (proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN_PET))
{
// spell_1
if(proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
@@ -1598,7 +1965,7 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
}
// allowed only in special format
- else if(proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN)
+ else if((proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN_PET))
{
sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId);
const_cast<ItemPrototype*>(proto)->Spells[0].SpellId = 0;
@@ -1608,7 +1975,7 @@ void ObjectMgr::LoadItemPrototypes()
}
// spell_3*,spell_4*,spell_5* is empty
- for (int j = 2; j < 5; j++)
+ for (int j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j)
{
if(proto->Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
{
@@ -1626,7 +1993,7 @@ void ObjectMgr::LoadItemPrototypes()
// normal spell list
else
{
- for (int j = 0; j < 5; j++)
+ for (int j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
{
if(proto->Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || proto->Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
{
@@ -1644,7 +2011,7 @@ void ObjectMgr::LoadItemPrototypes()
const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
}
// allowed only in special format
- else if(proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN)
+ else if((proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN_PET))
{
sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId);
const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
@@ -1692,10 +2059,39 @@ void ObjectMgr::LoadItemPrototypes()
if(proto->Map && !sMapStore.LookupEntry(proto->Map))
sLog.outErrorDb("Item (Entry: %u) has wrong Map (%u)",i,proto->Map);
+ if(proto->BagFamily)
+ {
+ // check bits
+ for(uint32 j = 0; j < sizeof(proto->BagFamily)*8; ++j)
+ {
+ uint32 mask = 1 << j;
+ if((proto->BagFamily & mask)==0)
+ continue;
+
+ ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1);
+ if(!bf)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit",i);
+ const_cast<ItemPrototype*>(proto)->BagFamily &= ~mask;
+ continue;
+ }
+
+ if(BAG_FAMILY_MASK_CURRENCY_TOKENS & mask)
+ {
+ CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(proto->ItemId);
+ if(!ctEntry)
+ {
+ sLog.outErrorDb("Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit",i);
+ const_cast<ItemPrototype*>(proto)->BagFamily &= ~mask;
+ }
+ }
+ }
+ }
+
if(proto->TotemCategory && !sTotemCategoryStore.LookupEntry(proto->TotemCategory))
sLog.outErrorDb("Item (Entry: %u) has wrong TotemCategory (%u)",i,proto->TotemCategory);
- for (int j = 0; j < 3; j++)
+ for (int j = 0; j < MAX_ITEM_PROTO_SOCKETS; j++)
{
if(proto->Socket[j].Color && (proto->Socket[j].Color & SOCKET_COLOR_ALL) != proto->Socket[j].Color)
{
@@ -1712,10 +2108,13 @@ void ObjectMgr::LoadItemPrototypes()
sLog.outErrorDb("Item (Entry: %u) has wrong FoodType value (%u)",i,proto->FoodType);
const_cast<ItemPrototype*>(proto)->FoodType = 0;
}
- }
- // this DBC used currently only for check item templates in DB.
- sItemStore.Clear();
+ if(proto->ItemLimitCategory && !sItemLimitCategoryStore.LookupEntry(proto->ItemLimitCategory))
+ {
+ sLog.outErrorDb("Item (Entry: %u) has wrong LimitCategory value (%u)",i,proto->ItemLimitCategory);
+ const_cast<ItemPrototype*>(proto)->ItemLimitCategory = 0;
+ }
+ }
}
void ObjectMgr::LoadPetLevelInfo()
@@ -1756,7 +2155,10 @@ void ObjectMgr::LoadPetLevelInfo()
if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level);
else
+ {
sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `pet_levelstats` table, ignoring.",current_level);
+ ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
+ }
continue;
}
else if(current_level < 1)
@@ -1999,7 +2401,7 @@ void ObjectMgr::LoadPlayerInfo()
if(sWorld.getConfig(CONFIG_START_ALL_SPELLS))
result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell_custom");
else
- result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell");
+ result = WorldDatabase.Query("SELECT race, class, Spell FROM playercreateinfo_spell");
uint32 count = 0;
@@ -2033,8 +2435,18 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
- PlayerInfo* pInfo = &playerInfo[current_race][current_class];
- pInfo->spell.push_back(CreateSpellPair(fields[2].GetUInt16(), fields[3].GetUInt8()));
+ if(!current_race || !current_class)
+ {
+ uint32 min_race = current_race ? current_race : 1;
+ uint32 max_race = current_race ? current_race + 1 : MAX_RACES;
+ uint32 min_class = current_class ? current_class : 1;
+ uint32 max_class = current_class ? current_class + 1 : MAX_CLASSES;
+ for(uint32 r = min_race; r < max_race; ++r)
+ for(uint32 c = min_class; c < max_class; ++c)
+ playerInfo[r][c].spell.push_back(fields[2].GetUInt32());
+ }
+ else
+ playerInfo[current_race][current_class].spell.push_back(fields[2].GetUInt32());
bar.step();
++count;
@@ -2139,7 +2551,10 @@ void ObjectMgr::LoadPlayerInfo()
if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level);
else
+ {
sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level);
+ ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
+ }
continue;
}
@@ -2234,7 +2649,10 @@ void ObjectMgr::LoadPlayerInfo()
if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level);
else
+ {
sLog.outDetail("Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_levelstats` table, ignoring.",current_level);
+ ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
+ }
continue;
}
@@ -2306,6 +2724,70 @@ void ObjectMgr::LoadPlayerInfo()
}
}
}
+
+ // Loading xp per level data
+ {
+ mPlayerXPperLevel.resize(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
+ for (uint32 level = 0; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
+ mPlayerXPperLevel[level] = 0;
+
+ // 0 1
+ QueryResult *result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level");
+
+ uint32 count = 0;
+
+ if (!result)
+ {
+ barGoLink bar( 1 );
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u xp for level definitions", count );
+ sLog.outErrorDb( "Error loading `player_xp_for_level` table or empty table.");
+ exit(1);
+ }
+
+ barGoLink bar( result->GetRowCount() );
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 current_level = fields[0].GetUInt32();
+ uint32 current_xp = fields[1].GetUInt32();
+
+ if(current_level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
+ {
+ if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
+ sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level);
+ else
+ {
+ sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level);
+ ++count; // make result loading percent "expected" correct in case disabled detail mode for example.
+ }
+ continue;
+ }
+ //PlayerXPperLevel
+ mPlayerXPperLevel[current_level] = current_xp;
+ bar.step();
+ ++count;
+ }
+ while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u xp for level definitions", count );
+ }
+
+ // fill level gaps
+ for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
+ {
+ if( mPlayerXPperLevel[level] == 0)
+ {
+ sLog.outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.",level+1, level);
+ mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100;
+ }
+ }
}
void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const
@@ -2550,15 +3032,15 @@ void ObjectMgr::LoadGroups()
result = CharacterDatabase.Query("SELECT memberGuid, assistant, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid");
if(!result)
{
- barGoLink bar( 1 );
- bar.step();
+ barGoLink bar2( 1 );
+ bar2.step();
}
else
{
- barGoLink bar( result->GetRowCount() );
+ barGoLink bar2( result->GetRowCount() );
do
{
- bar.step();
+ bar2.step();
Field *fields = result->Fetch();
count++;
leaderGuid = MAKE_NEW_GUID(fields[3].GetUInt32(), 0, HIGHGUID_PLAYER);
@@ -2610,15 +3092,15 @@ void ObjectMgr::LoadGroups()
if(!result)
{
- barGoLink bar( 1 );
- bar.step();
+ barGoLink bar2( 1 );
+ bar2.step();
}
else
{
- barGoLink bar( result->GetRowCount() );
+ barGoLink bar2( result->GetRowCount() );
do
{
- bar.step();
+ bar2.step();
Field *fields = result->Fetch();
count++;
leaderGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
@@ -2632,7 +3114,14 @@ void ObjectMgr::LoadGroups()
}
}
- InstanceSave *save = sInstanceSaveManager.AddInstanceSave(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true);
+ MapEntry const* mapEntry = sMapStore.LookupEntry(fields[1].GetUInt32());
+ if(!mapEntry || !mapEntry->IsDungeon())
+ {
+ sLog.outErrorDb("Incorrect entry in group_instance table : no dungeon map %d", fields[1].GetUInt32());
+ continue;
+ }
+
+ InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapEntry->MapID, fields[2].GetUInt32(), fields[4].GetUInt8(), (time_t)fields[5].GetUInt64(), (fields[6].GetUInt32() == 0), true);
group->BindToInstance(save, fields[3].GetBool(), true);
}while( result->NextRow() );
delete result;
@@ -2658,31 +3147,35 @@ void ObjectMgr::LoadQuests()
QueryResult *result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
// 9 10 11 12 13 14 15 16
"RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime,"
- // 17 18 19 20 21 22 23 24 25 26
- "QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
- // 27 28 29 30 31 32 33 34 35 36
+ // 17 18 19 20 21 22 23 24 25 26 27 28
+ "QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
+ // 29 30 31 32 33 34 35 36 37 38
"Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4,"
- // 37 38 39 40 41 42 43 44
+ // 39 40 41 42 43 44 45 46
"ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4,"
- // 45 46 47 48 49 50 51 52 53 54 54 55
- "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4,"
- // 57 58 59 60 61 62 63 64
+ // 47 48 49 50 51 52 53 54
+ "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4,"
+ // 55 56 57 58 59 60 61 62
"ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4,"
- // 65 66 67 68
+ // 63 64 65 66
"ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4,"
- // 69 70 71 72 73 74
+ // 67 68 69 70 71 72
"RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6,"
- // 75 76 77 78 79 80
+ // 73 74 75 76 77 78
"RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6,"
- // 81 82 83 84 85 86 87 88
+ // 79 80 81 82 83 84 85 86
"RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4,"
- // 89 90 91 92 93 94 95 96 97 98
+ // 87 88 89 90 91 92 93 94 95 96
"RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5,"
- // 99 100 101 102 103 104 105 106 107 108 109
+ // 97 98 99 100 101 102 103 104 105 106 107
"RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt,"
- // 110 111 112 113 114 115 116 117 118 119
- "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
- // 120 121
+ // 108 109 110 111 112 113 114 115
+ "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4,"
+ // 116 117 118 119 120 121
+ "IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
+ // 122 123 124 125
+ "OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4,"
+ // 126 127
"StartScript, CompleteScript"
" FROM quest_template");
if(result == NULL)
@@ -2854,10 +3347,10 @@ void ObjectMgr::LoadQuests()
// no changes, quest can't be done for this requirement
}
- if(qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > Player::Reputation_Cap)
+ if(qinfo->RequiredMinRepValue && qinfo->RequiredMinRepValue > ReputationMgr::Reputation_Cap)
{
sLog.outErrorDb("Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done.",
- qinfo->GetQuestId(),qinfo->RequiredMinRepValue,Player::Reputation_Cap);
+ qinfo->GetQuestId(),qinfo->RequiredMinRepValue,ReputationMgr::Reputation_Cap);
// no changes, quest can't be done for this requirement
}
@@ -2976,20 +3469,6 @@ void ObjectMgr::LoadQuests()
qinfo->GetQuestId(),j+1,id,id);
// no changes, quest can't be done for this requirement
}
-
- if(!qinfo->ReqSourceCount[j])
- {
- sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but `ReqSourceCount%d` = 0, quest can't be done.",
- qinfo->GetQuestId(),j+1,id,j+1);
- qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest
- }
-
- if(!qinfo->ReqSourceRef[j])
- {
- sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but `ReqSourceRef%d` = 0, quest can't be done.",
- qinfo->GetQuestId(),j+1,id,j+1);
- qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest
- }
}
else
{
@@ -2999,41 +3478,6 @@ void ObjectMgr::LoadQuests()
qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceCount[j]);
// no changes, quest ignore this data
}
-
- if(qinfo->ReqSourceRef[j]>0)
- {
- sLog.outErrorDb("Quest %u has `ReqSourceId%d` = 0 but `ReqSourceRef%d` = %u.",
- qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceRef[j]);
- // no changes, quest ignore this data
- }
- }
- }
-
- for(int j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j )
- {
- uint32 ref = qinfo->ReqSourceRef[j];
- if(ref)
- {
- if(ref > QUEST_OBJECTIVES_COUNT)
- {
- sLog.outErrorDb("Quest %u has `ReqSourceRef%d` = %u but max value in `ReqSourceRef%d` is %u, quest can't be done.",
- qinfo->GetQuestId(),j+1,ref,j+1,QUEST_OBJECTIVES_COUNT);
- // no changes, quest can't be done for this requirement
- }
- else
- if(!qinfo->ReqItemId[ref-1] && !qinfo->ReqSpell[ref-1])
- {
- sLog.outErrorDb("Quest %u has `ReqSourceRef%d` = %u but `ReqItemId%u` = 0 and `ReqSpellCast%u` = 0, quest can't be done.",
- qinfo->GetQuestId(),j+1,ref,ref,ref);
- // no changes, quest can't be done for this requirement
- }
- else if(qinfo->ReqItemId[ref-1] && qinfo->ReqSpell[ref-1])
- {
- sLog.outErrorDb("Quest %u has `ReqItemId%u` = %u and `ReqSpellCast%u` = %u, quest can't have both fields <> 0, then can't be done.",
- qinfo->GetQuestId(),ref,qinfo->ReqItemId[ref-1],ref,qinfo->ReqSpell[ref-1]);
- // no changes, quest can't be done for this requirement
- qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest
- }
}
}
@@ -3047,7 +3491,7 @@ void ObjectMgr::LoadQuests()
{
sLog.outErrorDb("Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done.",
qinfo->GetQuestId(),j+1,id,id);
- // no changes, quest can't be done for this requirement
+ continue;
}
if(!qinfo->ReqCreatureOrGOId[j])
@@ -3254,14 +3698,15 @@ void ObjectMgr::LoadQuests()
if(qinfo->NextQuestInChain)
{
- if(mQuestTemplates.find(qinfo->NextQuestInChain) == mQuestTemplates.end())
+ QuestMap::iterator qNextItr = mQuestTemplates.find(qinfo->NextQuestInChain);
+ if(qNextItr == mQuestTemplates.end())
{
sLog.outErrorDb("Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.",
qinfo->GetQuestId(),qinfo->NextQuestInChain ,qinfo->NextQuestInChain );
qinfo->NextQuestInChain = 0;
}
else
- mQuestTemplates[qinfo->NextQuestInChain]->prevChainQuests.push_back(qinfo->GetQuestId());
+ qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId());
}
// fill additional data stores
@@ -3279,14 +3724,15 @@ void ObjectMgr::LoadQuests()
if(qinfo->NextQuestId)
{
- if (mQuestTemplates.find(abs(qinfo->GetNextQuestId())) == mQuestTemplates.end())
+ QuestMap::iterator qNextItr = mQuestTemplates.find(abs(qinfo->GetNextQuestId()));
+ if (qNextItr == mQuestTemplates.end())
{
sLog.outErrorDb("Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId());
}
else
{
int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId());
- mQuestTemplates[abs(qinfo->GetNextQuestId())]->prevQuests.push_back(signedQuestId);
+ qNextItr->second->prevQuests.push_back(signedQuestId);
}
}
@@ -3327,7 +3773,7 @@ void ObjectMgr::LoadQuests()
}
sLog.outString();
- sLog.outString( ">> Loaded %u quests definitions", mQuestTemplates.size() );
+ sLog.outString( ">> Loaded %lu quests definitions", (unsigned long)mQuestTemplates.size() );
}
void ObjectMgr::LoadQuestLocales()
@@ -3352,7 +3798,7 @@ void ObjectMgr::LoadQuestLocales()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outString(">> Loaded 0 Quest locale strings. DB table `locales_quest` is empty.");
return;
}
@@ -3463,58 +3909,7 @@ void ObjectMgr::LoadQuestLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u Quest locale strings", mQuestLocaleMap.size() );
-}
-
-void ObjectMgr::LoadPetCreateSpells()
-{
- QueryResult *result = WorldDatabase.Query("SELECT entry, Spell1, Spell2, Spell3, Spell4 FROM petcreateinfo_spell");
- if(!result)
- {
- barGoLink bar( 1 );
- bar.step();
-
- sLog.outString();
- sLog.outString( ">> Loaded 0 pet create spells" );
- sLog.outErrorDb("`petcreateinfo_spell` table is empty!");
- return;
- }
-
- uint32 count = 0;
-
- barGoLink bar( result->GetRowCount() );
-
- mPetCreateSpell.clear();
-
- do
- {
- Field *fields = result->Fetch();
- bar.step();
-
- uint32 creature_id = fields[0].GetUInt32();
-
- if(!creature_id || !sCreatureStorage.LookupEntry<CreatureInfo>(creature_id))
- continue;
-
- PetCreateSpellEntry PetCreateSpell;
- for(int i = 0; i < 4; i++)
- {
- PetCreateSpell.spellid[i] = fields[i + 1].GetUInt32();
-
- if(PetCreateSpell.spellid[i] && !sSpellStore.LookupEntry(PetCreateSpell.spellid[i]))
- sLog.outErrorDb("Spell %u listed in `petcreateinfo_spell` does not exist",PetCreateSpell.spellid[i]);
- }
-
- mPetCreateSpell[creature_id] = PetCreateSpell;
-
- ++count;
- }
- while (result->NextRow());
-
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u pet create spells", count );
+ sLog.outString( ">> Loaded %lu Quest locale strings", (unsigned long)mQuestLocaleMap.size() );
}
void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
@@ -3584,6 +3979,16 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
break;
}
+ case SCRIPT_COMMAND_EMOTE:
+ {
+ if(!sEmotesStore.LookupEntry(tmp.datalong))
+ {
+ sLog.outErrorDb("Table `%s` has invalid emote id (datalong = %u) in SCRIPT_COMMAND_EMOTE for script id %u",tablename,tmp.datalong,tmp.id);
+ continue;
+ }
+ break;
+ }
+
case SCRIPT_COMMAND_TELEPORT_TO:
{
if(!sMapStore.LookupEntry(tmp.datalong))
@@ -3712,6 +4117,21 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
}
case SCRIPT_COMMAND_REMOVE_AURA:
+ {
+ if(!sSpellStore.LookupEntry(tmp.datalong))
+ {
+ sLog.outErrorDb("Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u",
+ tablename,tmp.datalong,tmp.id);
+ continue;
+ }
+ if(tmp.datalong2 & ~0x1) // 1 bits (0,1)
+ {
+ sLog.outErrorDb("Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u",
+ tablename,tmp.datalong2,tmp.id);
+ continue;
+ }
+ break;
+ }
case SCRIPT_COMMAND_CAST_SPELL:
{
if(!sSpellStore.LookupEntry(tmp.datalong))
@@ -3720,6 +4140,12 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
tablename,tmp.datalong,tmp.id);
continue;
}
+ if(tmp.datalong2 & ~0x3) // 2 bits
+ {
+ sLog.outErrorDb("Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u",
+ tablename,tmp.datalong2,tmp.id);
+ continue;
+ }
break;
}
}
@@ -3825,13 +4251,16 @@ void ObjectMgr::LoadEventScripts()
switch(goInfo->type)
{
case GAMEOBJECT_TYPE_GOOBER:
- if(goInfo->goober.eventId)
+ if (goInfo->goober.eventId)
evt_scripts.insert(goInfo->goober.eventId);
break;
case GAMEOBJECT_TYPE_CHEST:
- if(goInfo->chest.eventId)
+ if (goInfo->chest.eventId)
evt_scripts.insert(goInfo->chest.eventId);
break;
+ case GAMEOBJECT_TYPE_CAMERA:
+ if (goInfo->camera.eventID)
+ evt_scripts.insert(goInfo->camera.eventID);
default:
break;
}
@@ -3858,7 +4287,8 @@ void ObjectMgr::LoadEventScripts()
{
std::set<uint32>::const_iterator itr2 = evt_scripts.find(itr->first);
if (itr2 == evt_scripts.end())
- sLog.outErrorDb("Table `event_scripts` has script (Id: %u) not referring to any gameobject_template type 10 data2 field or type 3 data6 field or any spell effect %u", itr->first, SPELL_EFFECT_SEND_EVENT);
+ sLog.outErrorDb("Table `event_scripts` has script (Id: %u) not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field or any spell effect %u",
+ itr->first, SPELL_EFFECT_SEND_EVENT);
}
}
@@ -3968,7 +4398,7 @@ void ObjectMgr::LoadPageTextLocales()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outString(">> Loaded 0 PageText locale strings. DB table `locales_page_text` is empty.");
return;
}
@@ -4005,13 +4435,13 @@ void ObjectMgr::LoadPageTextLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u PageText locale strings", mPageTextLocaleMap.size() );
+ sLog.outString( ">> Loaded %lu PageText locale strings", (unsigned long)mPageTextLocaleMap.size() );
}
struct SQLInstanceLoader : public SQLStorageLoaderBase<SQLInstanceLoader>
{
template<class D>
- void convert_from_str(uint32 field_pos, char *src, D &dst)
+ void convert_from_str(uint32 /*field_pos*/, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
@@ -4035,14 +4465,20 @@ void ObjectMgr::LoadInstanceTemplate()
else if(!entry->HasResetTime())
continue;
+ //FIXME: now exist heroic instance, normal/heroic raid instances
+ // entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid)
+ // entry->resetTimeRaid store reset time for normal raid only
+ // for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode.
+ // but at some point wee need implement reset time dependent from raid instance mode
if(temp->reset_delay == 0)
{
// use defaults from the DBC
- if(entry->SupportsHeroicMode())
+ if(entry->resetTimeHeroic) // for both raid and non raids, read above
{
temp->reset_delay = entry->resetTimeHeroic / DAY;
}
else if (entry->resetTimeRaid && entry->map_type == MAP_RAID)
+ // for normal raid only
{
temp->reset_delay = entry->resetTimeRaid / DAY;
}
@@ -4056,27 +4492,16 @@ void ObjectMgr::LoadInstanceTemplate()
sLog.outString();
}
-void ObjectMgr::AddGossipText(GossipText *pGText)
+GossipText const *ObjectMgr::GetGossipText(uint32 Text_ID) const
{
- ASSERT( pGText->Text_ID );
- ASSERT( mGossipText.find(pGText->Text_ID) == mGossipText.end() );
- mGossipText[pGText->Text_ID] = pGText;
-}
-
-GossipText *ObjectMgr::GetGossipText(uint32 Text_ID)
-{
- GossipTextMap::const_iterator itr;
- for (itr = mGossipText.begin(); itr != mGossipText.end(); ++itr)
- {
- if(itr->second->Text_ID == Text_ID)
- return itr->second;
- }
+ GossipTextMap::const_iterator itr = mGossipText.find(Text_ID);
+ if(itr != mGossipText.end())
+ return &itr->second;
return NULL;
}
void ObjectMgr::LoadGossipText()
{
- GossipText *pGText;
QueryResult *result = WorldDatabase.Query( "SELECT * FROM npc_text" );
int count = 0;
@@ -4103,34 +4528,29 @@ void ObjectMgr::LoadGossipText()
bar.step();
- pGText = new GossipText;
- pGText->Text_ID = fields[cic++].GetUInt32();
-
- for (int i=0; i< 8; i++)
+ uint32 Text_ID = fields[cic++].GetUInt32();
+ if(!Text_ID)
{
- pGText->Options[i].Text_0 = fields[cic++].GetCppString();
- pGText->Options[i].Text_1 = fields[cic++].GetCppString();
-
- pGText->Options[i].Language = fields[cic++].GetUInt32();
- pGText->Options[i].Probability = fields[cic++].GetFloat();
+ sLog.outErrorDb("Table `npc_text` has record wit reserved id 0, ignore.");
+ continue;
+ }
- pGText->Options[i].Emotes[0]._Delay = fields[cic++].GetUInt32();
- pGText->Options[i].Emotes[0]._Emote = fields[cic++].GetUInt32();
+ GossipText& gText = mGossipText[Text_ID];
- pGText->Options[i].Emotes[1]._Delay = fields[cic++].GetUInt32();
- pGText->Options[i].Emotes[1]._Emote = fields[cic++].GetUInt32();
+ for (int i=0; i< 8; i++)
+ {
+ gText.Options[i].Text_0 = fields[cic++].GetCppString();
+ gText.Options[i].Text_1 = fields[cic++].GetCppString();
- pGText->Options[i].Emotes[2]._Delay = fields[cic++].GetUInt32();
- pGText->Options[i].Emotes[2]._Emote = fields[cic++].GetUInt32();
- }
+ gText.Options[i].Language = fields[cic++].GetUInt32();
+ gText.Options[i].Probability = fields[cic++].GetFloat();
- if ( !pGText->Text_ID ){
- delete pGText;
- continue;
+ for(int j=0; j < 3; ++j)
+ {
+ gText.Options[i].Emotes[j]._Delay = fields[cic++].GetUInt32();
+ gText.Options[i].Emotes[j]._Emote = fields[cic++].GetUInt32();
+ }
}
-
- AddGossipText( pGText );
-
} while( result->NextRow() );
sLog.outString();
@@ -4159,8 +4579,8 @@ void ObjectMgr::LoadNpcTextLocales()
bar.step();
- sLog.outString("");
- sLog.outString(">> Loaded 0 Quest locale strings. DB table `locales_npc_text` is empty.");
+ sLog.outString();
+ sLog.outString(">> Loaded 0 NpcText locale strings. DB table `locales_npc_text` is empty.");
return;
}
@@ -4210,7 +4630,7 @@ void ObjectMgr::LoadNpcTextLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u NpcText locale strings", mNpcTextLocaleMap.size() );
+ sLog.outString( ">> Loaded %lu NpcText locale strings", (unsigned long)mNpcTextLocaleMap.size() );
}
//not very fast function but it is called only once a day, or on starting-up
@@ -4220,18 +4640,31 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
sLog.outDebug("Returning mails current time: hour: %d, minute: %d, second: %d ", localtime(&basetime)->tm_hour, localtime(&basetime)->tm_min, localtime(&basetime)->tm_sec);
//delete all old mails without item and without body immediately, if starting server
if (!serverUp)
- CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" I64FMTD "' AND has_items = '0' AND itemTextId = 0", (uint64)basetime);
+ CharacterDatabase.PExecute("DELETE FROM mail WHERE expire_time < '" UI64FMTD "' AND has_items = '0' AND itemTextId = 0", (uint64)basetime);
// 0 1 2 3 4 5 6 7 8 9
- QueryResult* result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" I64FMTD "'", (uint64)basetime);
+ QueryResult* result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" UI64FMTD "'", (uint64)basetime);
if ( !result )
+ {
+ barGoLink bar(1);
+ bar.step();
+ sLog.outString();
+ sLog.outString(">> Only expired mails (need to be return or delete) or DB table `mail` is empty.");
return; // any mails need to be returned or deleted
- Field *fields;
+ }
+
//std::ostringstream delitems, delmails; //will be here for optimization
//bool deletemail = false, deleteitem = false;
//delitems << "DELETE FROM item_instance WHERE guid IN ( ";
//delmails << "DELETE FROM mail WHERE id IN ( "
+
+ barGoLink bar( result->GetRowCount() );
+ uint32 count = 0;
+ Field *fields;
+
do
{
+ bar.step();
+
fields = result->Fetch();
Mail *m = new Mail;
m->messageID = fields[0].GetUInt32();
@@ -4284,7 +4717,7 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
else
{
//mail will be returned:
- CharacterDatabase.PExecute("UPDATE mail SET sender = '%u', receiver = '%u', expire_time = '" I64FMTD "', deliver_time = '" I64FMTD "',cod = '0', checked = '%u' WHERE id = '%u'", m->receiver, m->sender, (uint64)(basetime + 30*DAY), (uint64)basetime, MAIL_CHECK_MASK_RETURNED, m->messageID);
+ CharacterDatabase.PExecute("UPDATE mail SET sender = '%u', receiver = '%u', expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',cod = '0', checked = '%u' WHERE id = '%u'", m->receiver, m->sender, (uint64)(basetime + 30*DAY), (uint64)basetime, MAIL_CHECK_MASK_RETURNED, m->messageID);
delete m;
continue;
}
@@ -4297,8 +4730,12 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
//delmails << m->messageID << ", ";
CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID);
delete m;
+ ++count;
} while (result->NextRow());
delete result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u mails", count );
}
void ObjectMgr::LoadQuestAreaTriggers()
@@ -4455,7 +4892,7 @@ void ObjectMgr::LoadAreaTriggerScripts()
sLog.outString( ">> Loaded %u areatrigger scripts", count );
}
-uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
+uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team )
{
bool found = false;
float dist;
@@ -4464,24 +4901,31 @@ uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid )
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i);
- if(node && node->map_id == mapid)
+ if(!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0])
+ continue;
+
+ uint8 field = (uint8)((i - 1) / 32);
+ uint32 submask = 1<<((i-1)%32);
+
+ // skip not taxi network nodes
+ if((sTaxiNodesMask[field] & submask)==0)
+ continue;
+
+ float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
+ if(found)
{
- float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z);
- if(found)
+ if(dist2 < dist)
{
- if(dist2 < dist)
- {
- dist = dist2;
- id = i;
- }
- }
- else
- {
- found = true;
dist = dist2;
id = i;
}
}
+ else
+ {
+ found = true;
+ dist = dist2;
+ id = i;
+ }
}
return id;
@@ -4511,7 +4955,7 @@ void ObjectMgr::GetTaxiPath( uint32 source, uint32 destination, uint32 &path, ui
path = dest_i->second.ID;
}
-uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
+uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team, bool allowed_alt_team /* = false */)
{
uint16 mount_entry = 0;
uint16 mount_id = 0;
@@ -4519,17 +4963,26 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
if(node)
{
- if (team == ALLIANCE) mount_entry = node->alliance_mount_type;
- else mount_entry = node->horde_mount_type;
+ if (team == ALLIANCE)
+ {
+ mount_entry = node->MountCreatureID[1];
+ if(!mount_entry && allowed_alt_team)
+ mount_entry = node->MountCreatureID[0];
- CreatureInfo const *cinfo = GetCreatureTemplate(mount_entry);
- if (cinfo)
+ CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
+ if(ci)
+ mount_id = ci->Modelid_A1;
+ }
+ if (team == HORDE)
{
- if(! (mount_id = cinfo->GetRandomValidModelId()))
- {
- sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry);
- return false;
- }
+ mount_entry = node->MountCreatureID[0];
+
+ if(!mount_entry && allowed_alt_team)
+ mount_entry = node->MountCreatureID[1];
+
+ CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
+ if(ci)
+ mount_id = ci->Modelid_H1;
}
}
@@ -4657,7 +5110,7 @@ void ObjectMgr::LoadGraveyardZones()
WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team)
{
// search for zone associated closest graveyard
- uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y);
+ uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y,z);
// Simulate std. algorithm:
// found some graveyard associated to (ghost_zone,ghost_map)
@@ -4668,7 +5121,10 @@ WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float
// then check faction
GraveYardMap::const_iterator graveLow = mGraveYardMap.lower_bound(zoneId);
GraveYardMap::const_iterator graveUp = mGraveYardMap.upper_bound(zoneId);
- if(graveLow==graveUp)
+ MapEntry const* map = sMapStore.LookupEntry(MapId);
+ // not need to check validity of map object; MapId _MUST_ be valid here
+
+ if(graveLow==graveUp && !map->IsBattleArena())
{
sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team);
return NULL;
@@ -4709,8 +5165,10 @@ WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float
if(MapId != entry->map_id)
{
// if find graveyard at different map from where entrance placed (or no entrance data), use any first
- if (!mapEntry || mapEntry->entrance_map < 0 || mapEntry->entrance_map != entry->map_id ||
- mapEntry->entrance_x == 0 && mapEntry->entrance_y == 0)
+ if (!mapEntry ||
+ mapEntry->entrance_map < 0 ||
+ mapEntry->entrance_map != entry->map_id ||
+ (mapEntry->entrance_x == 0 && mapEntry->entrance_y == 0))
{
// not have any corrdinates for check distance anyway
entryFar = entry;
@@ -4855,7 +5313,7 @@ void ObjectMgr::LoadAreaTriggerTeleports()
uint32 count = 0;
- // 0 1 2 3 4 5 6
+ // 0 1 2 3 4 5 6
QueryResult *result = WorldDatabase.Query("SELECT id, access_id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport");
if( !result )
{
@@ -4896,7 +5354,7 @@ void ObjectMgr::LoadAreaTriggerTeleports()
sLog.outErrorDb("Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.",Trigger_ID);
continue;
}
-
+
MapEntry const* mapEntry = sMapStore.LookupEntry(at.target_mapId);
if(!mapEntry)
{
@@ -5007,7 +5465,8 @@ void ObjectMgr::LoadAccessRequirements()
if(ar.heroicQuest)
{
- if(!GetQuestTemplate(ar.heroicQuest))
+ QuestMap::iterator qReqItr = mQuestTemplates.find(ar.heroicQuest);
+ if(qReqItr == mQuestTemplates.end())
{
sLog.outErrorDb("Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement.",ar.heroicQuest,requiremt_ID);
ar.heroicQuest = 0;
@@ -5016,7 +5475,8 @@ void ObjectMgr::LoadAccessRequirements()
if(ar.quest)
{
- if(!GetQuestTemplate(ar.quest))
+ QuestMap::iterator qReqItr = mQuestTemplates.find(ar.quest);
+ if(qReqItr == mQuestTemplates.end())
{
sLog.outErrorDb("Required Quest %u not exist for trigger %u, remove quest done requirement.",ar.quest,requiremt_ID);
ar.quest = 0;
@@ -5033,6 +5493,9 @@ void ObjectMgr::LoadAccessRequirements()
sLog.outString( ">> Loaded %u access requirement definitions", count );
}
+/*
+ * Searches for the areatrigger which teleports players out of the given map
+ */
AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
{
const MapEntry *mapEntry = sMapStore.LookupEntry(Map);
@@ -5049,6 +5512,23 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const
return NULL;
}
+/**
+ * Searches for the areatrigger which teleports players to the given map
+ */
+AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const
+{
+ for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr)
+ {
+ if(itr->second.target_mapId == Map)
+ {
+ AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first);
+ if(atEntry)
+ return &itr->second;
+ }
+ }
+ return NULL;
+}
+
void ObjectMgr::SetHighestGuids()
{
QueryResult *result = CharacterDatabase.Query( "SELECT MAX(guid) FROM characters" );
@@ -5065,9 +5545,6 @@ void ObjectMgr::SetHighestGuids()
delete result;
}
- // pet guids are not saved to DB, set to 0 (pet guid != pet id)
- m_hiPetGuid = 0;
-
result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" );
if( result )
{
@@ -5141,24 +5618,24 @@ uint32 ObjectMgr::GenerateArenaTeamId()
return m_arenaTeamId++;
}
-uint32 ObjectMgr::GenerateGuildId()
+uint32 ObjectMgr::GenerateAuctionID()
{
- if(m_guildId>=0xFFFFFFFE)
+ if(m_auctionid>=0xFFFFFFFE)
{
- sLog.outError("Guild ids overflow!! Can't continue, shutting down server. ");
+ sLog.outError("Auctions ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
- return m_guildId++;
+ return m_auctionid++;
}
-uint32 ObjectMgr::GenerateAuctionID()
+uint32 ObjectMgr::GenerateGuildId()
{
- if(m_auctionid>=0xFFFFFFFE)
+ if(m_guildId>=0xFFFFFFFE)
{
- sLog.outError("Auctions ids overflow!! Can't continue, shutting down server. ");
+ sLog.outError("Guild ids overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
- return m_auctionid++;
+ return m_guildId++;
}
uint32 ObjectMgr::GenerateMailID()
@@ -5220,6 +5697,13 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
World::StopNow(ERROR_EXIT_CODE);
}
return m_hiPetGuid++;
+ case HIGHGUID_VEHICLE:
+ if(m_hiVehicleGuid>=0x00FFFFFF)
+ {
+ sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
+ }
+ return m_hiVehicleGuid++;
case HIGHGUID_PLAYER:
if(m_hiCharGuid>=0xFFFFFFFE)
{
@@ -5271,7 +5755,7 @@ void ObjectMgr::LoadGameObjectLocales()
bar.step();
- sLog.outString("");
+ sLog.outString();
sLog.outString(">> Loaded 0 gameobject locale strings. DB table `locales_gameobject` is empty.");
return;
}
@@ -5303,9 +5787,9 @@ void ObjectMgr::LoadGameObjectLocales()
}
}
- for(int i = MAX_LOCALE; i < MAX_LOCALE*2-1; ++i)
+ for(int i = 1; i < MAX_LOCALE; ++i)
{
- std::string str = fields[i].GetCppString();
+ std::string str = fields[i+(MAX_LOCALE-1)].GetCppString();
if(!str.empty())
{
int idx = GetOrNewIndexForLocale(LocaleConstant(i));
@@ -5324,18 +5808,73 @@ void ObjectMgr::LoadGameObjectLocales()
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u gameobject locale strings", mGameObjectLocaleMap.size() );
+ sLog.outString( ">> Loaded %lu gameobject locale strings", (unsigned long)mGameObjectLocaleMap.size() );
}
struct SQLGameObjectLoader : public SQLStorageLoaderBase<SQLGameObjectLoader>
{
template<class D>
- void convert_from_str(uint32 field_pos, char *src, D &dst)
+ void convert_from_str(uint32 /*field_pos*/, char *src, D &dst)
{
dst = D(objmgr.GetScriptId(src));
}
};
+inline void CheckGOLockId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ if (sLockStore.LookupEntry(dataN))
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but lock (Id: %u) not found.",
+ goInfo->id,goInfo->type,N,goInfo->door.lockId,goInfo->door.lockId);
+}
+
+inline void CheckGOLinkedTrapId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ if (GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(dataN))
+ {
+ if (trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
+ goInfo->id,goInfo->type,N,dataN,dataN,GAMEOBJECT_TYPE_TRAP);
+ }
+ /* disable check for while (too many error reports baout not existed in trap templates
+ else
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
+ goInfo->id,goInfo->type,N,dataN,dataN);
+ */
+}
+
+inline void CheckGOSpellId(GameObjectInfo const* goInfo,uint32 dataN,uint32 N)
+{
+ if (sSpellStore.LookupEntry(dataN))
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist.",
+ goInfo->id,goInfo->type,N,dataN,dataN);
+}
+
+inline void CheckAndFixGOChairHeightId(GameObjectInfo const* goInfo,uint32 const& dataN,uint32 N)
+{
+ if (dataN <= (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) )
+ return;
+
+ sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but correct chair height in range 0..%i.",
+ goInfo->id,goInfo->type,N,dataN,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR);
+
+ // prevent client and server unexpected work
+ const_cast<uint32&>(dataN) = 0;
+}
+
+inline void CheckGONoDamageImmuneId(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) noDamageImmune field value.",
+ goInfo->id,goInfo->type,N,dataN);
+}
+
void ObjectMgr::LoadGameobjectInfo()
{
SQLGameObjectLoader loader;
@@ -5345,139 +5884,104 @@ void ObjectMgr::LoadGameobjectInfo()
for(uint32 id = 1; id < sGOStorage.MaxEntry; id++)
{
GameObjectInfo const* goInfo = sGOStorage.LookupEntry<GameObjectInfo>(id);
- if(!goInfo)
+ if (!goInfo)
continue;
switch(goInfo->type)
{
case GAMEOBJECT_TYPE_DOOR: //0
{
- if(goInfo->door.lockId)
- {
- if(!sLockStore.LookupEntry(goInfo->door.lockId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.",
- id,goInfo->type,goInfo->door.lockId,goInfo->door.lockId);
- }
+ if (goInfo->door.lockId)
+ CheckGOLockId(goInfo,goInfo->door.lockId,1);
+ CheckGONoDamageImmuneId(goInfo,goInfo->door.noDamageImmune,3);
break;
}
case GAMEOBJECT_TYPE_BUTTON: //1
{
- if(goInfo->button.lockId)
- {
- if(!sLockStore.LookupEntry(goInfo->button.lockId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but lock (Id: %u) not found.",
- id,goInfo->type,goInfo->button.lockId,goInfo->button.lockId);
- }
+ if (goInfo->button.lockId)
+ CheckGOLockId(goInfo,goInfo->button.lockId,1);
+ CheckGONoDamageImmuneId(goInfo,goInfo->button.noDamageImmune,4);
+ break;
+ }
+ case GAMEOBJECT_TYPE_QUESTGIVER: //2
+ {
+ if (goInfo->questgiver.lockId)
+ CheckGOLockId(goInfo,goInfo->questgiver.lockId,0);
+ CheckGONoDamageImmuneId(goInfo,goInfo->questgiver.noDamageImmune,5);
break;
}
case GAMEOBJECT_TYPE_CHEST: //3
{
- if(goInfo->chest.lockId)
- {
- if(!sLockStore.LookupEntry(goInfo->chest.lockId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but lock (Id: %u) not found.",
- id,goInfo->type,goInfo->chest.lockId,goInfo->chest.lockId);
- }
- if(goInfo->chest.linkedTrapId) // linked trap
- {
- if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->chest.linkedTrapId))
- {
- if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
- id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
- }
- /* disable check for while
- else
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
- id,goInfo->type,goInfo->chest.linkedTrapId,goInfo->chest.linkedTrapId);
- */
- }
+ if (goInfo->chest.lockId)
+ CheckGOLockId(goInfo,goInfo->chest.lockId,0);
+
+ if (goInfo->chest.linkedTrapId) // linked trap
+ CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7);
break;
}
case GAMEOBJECT_TYPE_TRAP: //6
{
- /* disable check for while
- if(goInfo->trap.spellId) // spell
- {
- if(!sSpellStore.LookupEntry(goInfo->trap.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->trap.spellId,goInfo->trap.spellId);
- }
+ if (goInfo->trap.lockId)
+ CheckGOLockId(goInfo,goInfo->trap.lockId,0);
+ /* disable check for while, too many not existed spells
+ if (goInfo->trap.spellId) // spell
+ CheckGOSpellId(goInfo,goInfo->trap.spellId,3);
*/
break;
}
case GAMEOBJECT_TYPE_CHAIR: //7
- if(goInfo->chair.height > 2)
- {
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..2.",
- id,goInfo->type,goInfo->chair.height);
-
- // prevent client and server unexpected work
- const_cast<GameObjectInfo*>(goInfo)->chair.height = 0;
- }
+ CheckAndFixGOChairHeightId(goInfo,goInfo->chair.height,1);
break;
case GAMEOBJECT_TYPE_SPELL_FOCUS: //8
{
- if(goInfo->spellFocus.focusId)
+ if (goInfo->spellFocus.focusId)
{
- if(!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId))
+ if (!sSpellFocusObjectStore.LookupEntry(goInfo->spellFocus.focusId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but SpellFocus (Id: %u) not exist.",
id,goInfo->type,goInfo->spellFocus.focusId,goInfo->spellFocus.focusId);
}
- if(goInfo->spellFocus.linkedTrapId) // linked trap
- {
- if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->spellFocus.linkedTrapId))
- {
- if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
- id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
- }
- /* disable check for while
- else
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
- id,goInfo->type,goInfo->spellFocus.linkedTrapId,goInfo->spellFocus.linkedTrapId);
- */
- }
+ if (goInfo->spellFocus.linkedTrapId) // linked trap
+ CheckGOLinkedTrapId(goInfo,goInfo->spellFocus.linkedTrapId,2);
break;
}
case GAMEOBJECT_TYPE_GOOBER: //10
{
- if(goInfo->goober.pageId) // pageId
+ if (goInfo->goober.lockId)
+ CheckGOLockId(goInfo,goInfo->goober.lockId,0);
+
+ if (goInfo->goober.pageId) // pageId
{
- if(!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
+ if (!sPageTextStore.LookupEntry<PageText>(goInfo->goober.pageId))
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist.",
id,goInfo->type,goInfo->goober.pageId,goInfo->goober.pageId);
}
- /* disable check for while
- if(goInfo->goober.spellId) // spell
- {
- if(!sSpellStore.LookupEntry(goInfo->goober.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data2=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->goober.spellId,goInfo->goober.spellId);
- }
+ /* disable check for while, too many not existed spells
+ if (goInfo->goober.spellId) // spell
+ CheckGOSpellId(goInfo,goInfo->goober.spellId,10);
*/
- if(goInfo->goober.linkedTrapId) // linked trap
- {
- if(GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(goInfo->goober.linkedTrapId))
- {
- if(trapInfo->type!=GAMEOBJECT_TYPE_TRAP)
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type.",
- id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId,GAMEOBJECT_TYPE_TRAP);
- }
- /* disable check for while
- else
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data12=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
- id,goInfo->type,goInfo->goober.linkedTrapId,goInfo->goober.linkedTrapId);
- */
- }
+ CheckGONoDamageImmuneId(goInfo,goInfo->goober.noDamageImmune,11);
+ if (goInfo->goober.linkedTrapId) // linked trap
+ CheckGOLinkedTrapId(goInfo,goInfo->goober.linkedTrapId,12);
+ break;
+ }
+ case GAMEOBJECT_TYPE_AREADAMAGE: //12
+ {
+ if (goInfo->areadamage.lockId)
+ CheckGOLockId(goInfo,goInfo->areadamage.lockId,0);
+ break;
+ }
+ case GAMEOBJECT_TYPE_CAMERA: //13
+ {
+ if (goInfo->camera.lockId)
+ CheckGOLockId(goInfo,goInfo->camera.lockId,0);
break;
}
case GAMEOBJECT_TYPE_MO_TRANSPORT: //15
{
- if(goInfo->moTransport.taxiPathId)
+ if (goInfo->moTransport.taxiPathId)
{
- if(goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty())
+ if (goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size() || sTaxiPathNodesByPath[goInfo->moTransport.taxiPathId].empty())
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.",
id,goInfo->type,goInfo->moTransport.taxiPathId,goInfo->moTransport.taxiPathId);
}
@@ -5485,26 +5989,41 @@ void ObjectMgr::LoadGameobjectInfo()
}
case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18
{
- /* disabled
- if(goInfo->summoningRitual.spellId)
- {
- if(!sSpellStore.LookupEntry(goInfo->summoningRitual.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->summoningRitual.spellId,goInfo->summoningRitual.spellId);
- }
+ /* disable check for while, too many not existed spells
+ // always must have spell
+ CheckGOSpellId(goInfo,goInfo->summoningRitual.spellId,1);
*/
break;
}
case GAMEOBJECT_TYPE_SPELLCASTER: //22
{
- if(goInfo->spellcaster.spellId) // spell
- {
- if(!sSpellStore.LookupEntry(goInfo->spellcaster.spellId))
- sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data3=%u but Spell (Entry %u) not exist.",
- id,goInfo->type,goInfo->spellcaster.spellId,goInfo->spellcaster.spellId);
- }
+ // always must have spell
+ CheckGOSpellId(goInfo,goInfo->spellcaster.spellId,0);
+ break;
+ }
+ case GAMEOBJECT_TYPE_FLAGSTAND: //24
+ {
+ if (goInfo->flagstand.lockId)
+ CheckGOLockId(goInfo,goInfo->flagstand.lockId,0);
+ CheckGONoDamageImmuneId(goInfo,goInfo->flagstand.noDamageImmune,5);
+ break;
+ }
+ case GAMEOBJECT_TYPE_FISHINGHOLE: //25
+ {
+ if (goInfo->fishinghole.lockId)
+ CheckGOLockId(goInfo,goInfo->fishinghole.lockId,4);
+ break;
+ }
+ case GAMEOBJECT_TYPE_FLAGDROP: //26
+ {
+ if (goInfo->flagdrop.lockId)
+ CheckGOLockId(goInfo,goInfo->flagdrop.lockId,0);
+ CheckGONoDamageImmuneId(goInfo,goInfo->flagdrop.noDamageImmune,3);
break;
}
+ case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
+ CheckAndFixGOChairHeightId(goInfo,goInfo->barberChair.chairheight,0);
+ break;
}
}
@@ -5553,6 +6072,13 @@ uint32 ObjectMgr::GetBaseXP(uint32 level)
return mBaseXPTable[level] ? mBaseXPTable[level] : 0;
}
+uint32 ObjectMgr::GetXPForLevel(uint32 level)
+{
+ if (level < mPlayerXPperLevel.size())
+ return mPlayerXPperLevel[level];
+ return 0;
+}
+
void ObjectMgr::LoadPetNames()
{
uint32 count = 0;
@@ -5754,6 +6280,131 @@ void ObjectMgr::LoadReputationOnKill()
sLog.outString(">> Loaded %u creature award reputation definitions", count);
}
+void ObjectMgr::LoadPointsOfInterest()
+{
+ uint32 count = 0;
+
+ // 0 1 2 3 4 5
+ QueryResult *result = WorldDatabase.Query("SELECT entry, x, y, icon, flags, data, icon_name FROM points_of_interest");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+
+ uint32 point_id = fields[0].GetUInt32();
+
+ PointOfInterest POI;
+ POI.x = fields[1].GetFloat();
+ POI.y = fields[2].GetFloat();
+ POI.icon = fields[3].GetUInt32();
+ POI.flags = fields[4].GetUInt32();
+ POI.data = fields[5].GetUInt32();
+ POI.icon_name = fields[6].GetCppString();
+
+ if(!MaNGOS::IsValidMapCoord(POI.x,POI.y))
+ {
+ sLog.outErrorDb("Table `points_of_interest` (Entry: %u) have invalid coordinates (X: %f Y: %f), ignored.",point_id,POI.x,POI.y);
+ continue;
+ }
+
+ mPointsOfInterest[point_id] = POI;
+
+ ++count;
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u Points of Interest definitions", count);
+}
+
+void ObjectMgr::LoadNPCSpellClickSpells()
+{
+ uint32 count = 0;
+
+ mSpellClickInfoMap.clear();
+
+ QueryResult *result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_id, quest_status, cast_flags FROM npc_spellclick_spells");
+
+ if(!result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty.");
+ return;
+ }
+
+ barGoLink bar(result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+
+ uint32 npc_entry = fields[0].GetUInt32();
+ CreatureInfo const* cInfo = GetCreatureTemplate(npc_entry);
+ if (!cInfo)
+ {
+ sLog.outErrorDb("Table npc_spellclick_spells references unknown creature_template %u. Skipping entry.", npc_entry);
+ continue;
+ }
+
+ uint32 spellid = fields[1].GetUInt32();
+ SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid);
+ if (!spellinfo)
+ {
+ sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", spellid);
+ continue;
+ }
+
+ uint32 quest = fields[2].GetUInt32();
+
+ // quest might be 0 to enable spellclick independent of any quest
+ if (quest)
+ {
+ if(mQuestTemplates.find(quest) == mQuestTemplates.end())
+ {
+ sLog.outErrorDb("Table npc_spellclick_spells references unknown quest %u. Skipping entry.", spellid);
+ continue;
+ }
+
+ }
+
+ uint32 queststatus = fields[3].GetUInt32();
+
+ uint8 castFlags = fields[4].GetUInt8();
+ SpellClickInfo info;
+ info.spellId = spellid;
+ info.questId = quest;
+ info.questStatus = queststatus;
+ info.castFlags = castFlags;
+ mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info));
+ ++count;
+ } while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u spellclick definitions", count);
+}
+
void ObjectMgr::LoadWeatherZoneChances()
{
uint32 count = 0;
@@ -5792,19 +6443,19 @@ void ObjectMgr::LoadWeatherZoneChances()
if(wzc.data[season].rainChance > 100)
{
wzc.data[season].rainChance = 25;
- sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%",zone_id,season);
+ sLog.outErrorDb("Weather for zone %u season %u has wrong rain chance > 100%%",zone_id,season);
}
if(wzc.data[season].snowChance > 100)
{
wzc.data[season].snowChance = 25;
- sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%",zone_id,season);
+ sLog.outErrorDb("Weather for zone %u season %u has wrong snow chance > 100%%",zone_id,season);
}
if(wzc.data[season].stormChance > 100)
{
wzc.data[season].stormChance = 25;
- sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%",zone_id,season);
+ sLog.outErrorDb("Weather for zone %u season %u has wrong storm chance > 100%%",zone_id,season);
}
}
@@ -5822,7 +6473,7 @@ void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t
mCreatureRespawnTimes[MAKE_PAIR64(loguid,instance)] = t;
WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance);
if(t)
- WorldDatabase.PExecute("INSERT INTO creature_respawn VALUES ( '%u', '" I64FMTD "', '%u' )", loguid, uint64(t), instance);
+ WorldDatabase.PExecute("INSERT INTO creature_respawn VALUES ( '%u', '" UI64FMTD "', '%u' )", loguid, uint64(t), instance);
}
void ObjectMgr::DeleteCreatureData(uint32 guid)
@@ -5840,7 +6491,7 @@ void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t)
mGORespawnTimes[MAKE_PAIR64(loguid,instance)] = t;
WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE guid = '%u' AND instance = '%u'", loguid, instance);
if(t)
- WorldDatabase.PExecute("INSERT INTO gameobject_respawn VALUES ( '%u', '" I64FMTD "', '%u' )", loguid, uint64(t), instance);
+ WorldDatabase.PExecute("INSERT INTO gameobject_respawn VALUES ( '%u', '" UI64FMTD "', '%u' )", loguid, uint64(t), instance);
}
void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance)
@@ -6021,11 +6672,18 @@ void ObjectMgr::LoadReservedPlayersNames()
bar.step();
fields = result->Fetch();
std::string name= fields[0].GetCppString();
- if(normalizePlayerName(name))
+
+ std::wstring wstr;
+ if(!Utf8toWStr (name,wstr))
{
- m_ReservedNames.insert(name);
- ++count;
+ sLog.outError("Table `reserved_name` have invalid name: %s", name.c_str() );
+ continue;
}
+
+ wstrToLower(wstr);
+
+ m_ReservedNames.insert(wstr);
+ ++count;
} while ( result->NextRow() );
delete result;
@@ -6034,6 +6692,17 @@ void ObjectMgr::LoadReservedPlayersNames()
sLog.outString( ">> Loaded %u reserved player names", count );
}
+bool ObjectMgr::IsReservedName( const std::string& name ) const
+{
+ std::wstring wstr;
+ if(!Utf8toWStr (name,wstr))
+ return false;
+
+ wstrToLower(wstr);
+
+ return m_ReservedNames.find(wstr) != m_ReservedNames.end();
+}
+
enum LanguageType
{
LT_BASIC_LATIN = 0x0000,
@@ -6182,55 +6851,26 @@ int ObjectMgr::GetOrNewIndexForLocale( LocaleConstant loc )
return m_LocalForIndex.size()-1;
}
-void ObjectMgr::LoadBattleMastersEntry()
+void ObjectMgr::LoadGameObjectForQuests()
{
- mBattleMastersMap.clear(); // need for reload case
-
- QueryResult *result = WorldDatabase.Query( "SELECT entry,bg_template FROM battlemaster_entry" );
-
- uint32 count = 0;
+ mGameObjectForQuestSet.clear(); // need for reload case
- if( !result )
+ if( !sGOStorage.MaxEntry )
{
barGoLink bar( 1 );
bar.step();
-
sLog.outString();
- sLog.outString( ">> Loaded 0 battlemaster entries - table is empty!" );
+ sLog.outString( ">> Loaded 0 GameObjects for quests" );
return;
}
- barGoLink bar( result->GetRowCount() );
-
- do
- {
- ++count;
- bar.step();
-
- Field *fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
- uint32 bgTypeId = fields[1].GetUInt32();
-
- mBattleMastersMap[entry] = bgTypeId;
-
- } while( result->NextRow() );
-
- delete result;
-
- sLog.outString();
- sLog.outString( ">> Loaded %u battlemaster entries", count );
-}
-
-void ObjectMgr::LoadGameObjectForQuests()
-{
- mGameObjectForQuestSet.clear(); // need for reload case
-
+ barGoLink bar( sGOStorage.MaxEntry - 1 );
uint32 count = 0;
// collect GO entries for GO that must activated
for(uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry)
{
+ bar.step();
GameObjectInfo const* goInfo = sGOStorage.LookupEntry<GameObjectInfo>(go_entry);
if(!goInfo)
continue;
@@ -6265,34 +6905,55 @@ void ObjectMgr::LoadGameObjectForQuests()
}
sLog.outString();
- sLog.outString( ">> Loaded %u GameObject for quests", count );
+ sLog.outString( ">> Loaded %u GameObjects for quests", count );
}
bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value)
{
- // cleanup affected map part for reloading case
- for(TrinityStringLocaleMap::iterator itr = mTrinityStringLocaleMap.begin(); itr != mTrinityStringLocaleMap.end();)
+ int32 start_value = min_value;
+ int32 end_value = max_value;
+ // some string can have negative indexes range
+ if (start_value < 0)
{
- if(itr->first >= min_value && itr->first <= max_value)
+ if (end_value >= start_value)
{
- TrinityStringLocaleMap::iterator itr2 = itr;
- ++itr;
- mTrinityStringLocaleMap.erase(itr2);
+ sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value);
+ return false;
+ }
+
+ // real range (max+1,min+1) exaple: (-10,-1000) -> -999...-10+1
+ std::swap(start_value,end_value);
+ ++start_value;
+ ++end_value;
+ }
+ else
+ {
+ if (start_value >= end_value)
+ {
+ sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value);
+ return false;
}
+ }
+
+ // cleanup affected map part for reloading case
+ for(TrinityStringLocaleMap::iterator itr = mTrinityStringLocaleMap.begin(); itr != mTrinityStringLocaleMap.end();)
+ {
+ if (itr->first >= start_value && itr->first < end_value)
+ mTrinityStringLocaleMap.erase(itr++);
else
++itr;
}
QueryResult *result = db.PQuery("SELECT entry,content_default,content_loc1,content_loc2,content_loc3,content_loc4,content_loc5,content_loc6,content_loc7,content_loc8 FROM %s",table);
- if(!result)
+ if (!result)
{
barGoLink bar(1);
bar.step();
- sLog.outString("");
- if(min_value == MIN_TRINITY_STRING_ID) // error only in case internal strings
+ sLog.outString();
+ if (min_value == MIN_TRINITY_STRING_ID) // error only in case internal strings
sLog.outErrorDb(">> Loaded 0 trinity strings. DB table `%s` is empty. Cannot continue.",table);
else
sLog.outString(">> Loaded 0 string templates. DB table `%s` is empty.",table);
@@ -6310,22 +6971,20 @@ bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 mi
int32 entry = fields[0].GetInt32();
- if(entry==0)
+ if (entry==0)
{
sLog.outErrorDb("Table `%s` contain reserved entry 0, ignored.",table);
continue;
}
- else if(entry < min_value || entry > max_value)
+ else if (entry < start_value || entry >= end_value)
{
- int32 start = min_value > 0 ? min_value : max_value;
- int32 end = min_value > 0 ? max_value : min_value;
- sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,start,end);
+ sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,min_value,max_value);
continue;
}
TrinityStringLocale& data = mTrinityStringLocaleMap[entry];
- if(data.Content.size() > 0)
+ if (data.Content.size() > 0)
{
sLog.outErrorDb("Table `%s` contain data for already loaded entry %i (from another table?), ignored.",table,entry);
continue;
@@ -6340,13 +6999,13 @@ bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 mi
for(int i = 1; i < MAX_LOCALE; ++i)
{
std::string str = fields[i+1].GetCppString();
- if(!str.empty())
+ if (!str.empty())
{
int idx = GetOrNewIndexForLocale(LocaleConstant(i));
- if(idx >= 0)
+ if (idx >= 0)
{
// 0 -> default, idx in to idx+1
- if(data.Content.size() <= idx+1)
+ if (data.Content.size() <= idx+1)
data.Content.resize(idx+2);
data.Content[idx+1] = str;
@@ -6358,7 +7017,7 @@ bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 mi
delete result;
sLog.outString();
- if(min_value == MIN_TRINITY_STRING_ID) // internal Trinity strings
+ if (min_value == MIN_TRINITY_STRING_ID)
sLog.outString( ">> Loaded %u Trinity strings from table %s", count,table);
else
sLog.outString( ">> Loaded %u string templates from %s", count,table);
@@ -6534,17 +7193,17 @@ bool PlayerCondition::Meets(Player const * player) const
case CONDITION_NONE:
return true; // empty condition, always met
case CONDITION_AURA:
- return player->HasAura(value1, value2);
+ return player->HasAuraEffect(value1, value2);
case CONDITION_ITEM:
return player->HasItemCount(value1, value2);
case CONDITION_ITEM_EQUIPPED:
- return player->GetItemOrItemWithGemEquipped(value1) != NULL;
+ return player->HasItemOrGemWithIdEquipped(value1,1);
case CONDITION_ZONEID:
return player->GetZoneId() == value1;
case CONDITION_REPUTATION_RANK:
{
FactionEntry const* faction = sFactionStore.LookupEntry(value1);
- return faction && player->GetReputationRank(faction) >= value2;
+ return faction && player->GetReputationMgr().GetRank(faction) >= value2;
}
case CONDITION_TEAM:
return player->GetTeam() == value1;
@@ -6561,12 +7220,12 @@ bool PlayerCondition::Meets(Player const * player) const
{
Unit::AuraMap const& auras = player->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual==3580)
+ if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580)
return true;
return false;
}
case CONDITION_NO_AURA:
- return !player->HasAura(value1, value2);
+ return !player->HasAuraEffect(value1, value2);
case CONDITION_ACTIVE_EVENT:
return gameeventmgr.IsActiveEvent(value1);
case CONDITION_INSTANCE_DATA:
@@ -6711,7 +7370,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
}
case CONDITION_ACTIVE_EVENT:
{
- GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
+ GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if(value1 >=events.size() || !events[value1].isValid())
{
sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1);
@@ -6722,6 +7381,8 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
case CONDITION_INSTANCE_DATA:
//TODO: need some check
break;
+ case CONDITION_NONE:
+ break;
}
return true;
}
@@ -6738,7 +7399,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
return SKILL_RANGE_MONO;
case SKILL_CATEGORY_ARMOR:
case SKILL_CATEGORY_CLASS:
- if(pSkill->id != SKILL_POISONS && pSkill->id != SKILL_LOCKPICKING)
+ if(pSkill->id != SKILL_LOCKPICKING)
return SKILL_RANGE_MONO;
else
return SKILL_RANGE_LEVEL;
@@ -6753,7 +7414,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
return SKILL_RANGE_MONO;
default:
case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc
- case SKILL_CATEGORY_NOT_DISPLAYED: //only GENEREC(DND)
+ case SKILL_CATEGORY_GENERIC: //only GENERIC(DND)
return SKILL_RANGE_NONE;
}
}
@@ -6814,11 +7475,10 @@ void ObjectMgr::LoadGameTele()
++count;
}
while (result->NextRow());
-
delete result;
sLog.outString();
- sLog.outString( ">> Loaded %u game tele's", count );
+ sLog.outString( ">> Loaded %u GameTeleports", count );
}
GameTele const* ObjectMgr::GetGameTele(const std::string& name) const
@@ -6954,30 +7614,41 @@ void ObjectMgr::LoadTrainerSpell()
continue;
}
- TrainerSpell* pTrainerSpell = new TrainerSpell();
- pTrainerSpell->spell = spell;
- pTrainerSpell->spellcost = fields[2].GetUInt32();
- pTrainerSpell->reqskill = fields[3].GetUInt32();
- pTrainerSpell->reqskillvalue = fields[4].GetUInt32();
- pTrainerSpell->reqlevel = fields[5].GetUInt32();
+ TrainerSpellData& data = m_mCacheTrainerSpellMap[entry];
- if(!pTrainerSpell->reqlevel)
- pTrainerSpell->reqlevel = spellinfo->spellLevel;
+ TrainerSpell& trainerSpell = data.spellList[spell];
+ trainerSpell.spell = spell;
+ trainerSpell.spellCost = fields[2].GetUInt32();
+ trainerSpell.reqSkill = fields[3].GetUInt32();
+ trainerSpell.reqSkillValue = fields[4].GetUInt32();
+ trainerSpell.reqLevel = fields[5].GetUInt32();
+ if(!trainerSpell.reqLevel)
+ trainerSpell.reqLevel = spellinfo->spellLevel;
- TrainerSpellData& data = m_mCacheTrainerSpellMap[entry];
+ // calculate learned spell for profession case when stored cast-spell
+ trainerSpell.learnedSpell = spell;
+ for(int i = 0; i <3; ++i)
+ {
+ if(spellinfo->Effect[i] != SPELL_EFFECT_LEARN_SPELL)
+ continue;
+ if(SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i]))
+ {
+ trainerSpell.learnedSpell = spellinfo->EffectTriggerSpell[i];
+ break;
+ }
+ }
- if(SpellMgr::IsProfessionSpell(spell))
+ if(SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell))
data.trainerType = 2;
- data.spellList.push_back(pTrainerSpell);
++count;
} while (result->NextRow());
delete result;
sLog.outString();
- sLog.outString( ">> Loaded Trainers %d", count );
+ sLog.outString( ">> Loaded %d Trainers", count );
}
void ObjectMgr::LoadVendors()
@@ -7255,16 +7926,30 @@ void ObjectMgr::LoadScriptNames()
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''");
- if(result)
+
+ if( !result )
{
- do
- {
- m_scriptNames.push_back((*result)[0].GetString());
- } while (result->NextRow());
- delete result;
+ barGoLink bar( 1 );
+ bar.step();
+ sLog.outString();
+ sLog.outErrorDb(">> Loaded empty set of Script Names!");
+ return;
}
+ barGoLink bar( result->GetRowCount() );
+ uint32 count = 0;
+
+ do
+ {
+ bar.step();
+ m_scriptNames.push_back((*result)[0].GetString());
+ ++count;
+ } while (result->NextRow());
+ delete result;
+
std::sort(m_scriptNames.begin(), m_scriptNames.end());
+ sLog.outString();
+ sLog.outString( ">> Loaded %d Script Names", count );
}
uint32 ObjectMgr::GetScriptId(const char *name)
@@ -7284,13 +7969,16 @@ void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set<int32>& ids)
{
for(ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM)
{
- if(itrM->second.dataint)
+ switch(itrM->second.command)
{
- if(!GetTrinityStringLocale (itrM->second.dataint))
- sLog.outErrorDb( "Table `db_script_string` has not existed string id %u", itrM->first);
+ case SCRIPT_COMMAND_TALK:
+ {
+ if(!GetTrinityStringLocale (itrM->second.dataint))
+ sLog.outErrorDb( "Table `db_script_string` not has string id %u used db script (ID: %u)", itrM->second.dataint, itrMM->first);
- if(ids.count(itrM->second.dataint))
- ids.erase(itrM->second.dataint);
+ if(ids.count(itrM->second.dataint))
+ ids.erase(itrM->second.dataint);
+ }
}
}
}
@@ -7326,15 +8014,15 @@ uint32 GetAreaTriggerScriptId(uint32 trigger_id)
bool LoadTrinityStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value)
{
- if(start_value >= 0 || start_value <= end_value) // start/end reversed for negative values
+ // MAX_DB_SCRIPT_STRING_ID is max allowed negative value for scripts (scrpts can use only more deep negative values
+ // start/end reversed for negative values
+ if (start_value > MAX_DB_SCRIPT_STRING_ID || end_value >= start_value)
{
- sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), use (%d - %d) instead.",table,start_value,end_value,-1,std::numeric_limits<int32>::min());
- start_value = -1;
- end_value = std::numeric_limits<int32>::min();
+ sLog.outErrorDb("Table '%s' attempt loaded with reserved by mangos range (%d - %d), strings not loaded.",table,start_value,end_value+1);
+ return false;
}
- // for scripting localized strings allowed use _only_ negative entries
- return objmgr.LoadTrinityStrings(db,table,end_value,start_value);
+ return objmgr.LoadTrinityStrings(db,table,start_value,end_value);
}
uint32 TRINITY_DLL_SPEC GetScriptId(const char *name)
@@ -7357,16 +8045,6 @@ CreatureInfo const *GetCreatureInfo(uint32 id)
return objmgr.GetCreatureTemplate(id);
}
-CreatureInfo const* GetCreatureTemplateStore(uint32 entry)
-{
- return sCreatureStorage.LookupEntry<CreatureInfo>(entry);
-}
-
-Quest const* GetQuestTemplateStore(uint32 entry)
-{
- return objmgr.GetQuestTemplate(entry);
-}
-
void ObjectMgr::LoadTransportEvents()
{
@@ -7403,3 +8081,12 @@ void ObjectMgr::LoadTransportEvents()
delete result;
}
+CreatureInfo const* GetCreatureTemplateStore(uint32 entry)
+{
+ return sCreatureStorage.LookupEntry<CreatureInfo>(entry);
+}
+
+Quest const* GetQuestTemplateStore(uint32 entry)
+{
+ return objmgr.GetQuestTemplate(entry);
+}