aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Globals/ObjectMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp466
1 files changed, 137 insertions, 329 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index a0ec6d3c411..78179a5534c 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -353,23 +353,23 @@ void ObjectMgr::LoadCreatureTemplates()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8
- // "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, "
- // 9 10 11 12 13
- // "TitleAlt, IconName, HealthScalingExpansion, RequiredExpansion, VignetteID, "
- // 14 15 16 17 18 19 20 21 22 23 24
+ // 0 1 2 3 4 5
+ // "SELECT entry, KillCredit1, KillCredit2, name, femaleName, subname, "
+ // 6 7 8 9
+ // "TitleAlt, IconName, RequiredExpansion, VignetteID, "
+ // 10 11 12 13 14 15 16 17 18 19 20
// "faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, "
- // 25 26 27 28 29 30 31 32
+ // 21 22 23 24 25 26 27 28
// "unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, "
- // 33 34 35 36 37 38 39 40 41 42
- // "type_flags, type_flags2, lootid, pickpocketloot, skinloot, VehicleId, mingold, maxgold, AIName, MovementType, "
- // 43 44 45 46 47 48 49 50 51 52 53 54 55 56
- // "ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, "
- // 57 58 59 60 61 62
- // "RacialLeader, movementId, CreatureDifficultyID, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, "
- // 63 64 65
+ // 29 30 31
+ // "VehicleId, AIName, MovementType, "
+ // 32 33 34 35 36 38 38 39
+ // "ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, ExperienceModifier, "
+ // 40 41 42 43 44
+ // "RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, "
+ // 45 46 47
// "mechanic_immune_mask, spell_school_immune_mask, flags_extra, "
- // 66 67
+ // 48 49
// "ScriptName, StringId FROM creature_template WHERE entry = ? OR 1 = ?");
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEMPLATE);
@@ -412,44 +412,35 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.Entry = entry;
- for (uint32 i = 0; i < MAX_CREATURE_DIFFICULTIES; ++i)
- creatureTemplate.DifficultyEntry[i] = fields[1 + i].GetUInt32();
-
for (uint8 i = 0; i < MAX_KILL_CREDIT; ++i)
- creatureTemplate.KillCredit[i] = fields[4 + i].GetUInt32();
-
- creatureTemplate.Name = fields[6].GetString();
- creatureTemplate.FemaleName = fields[7].GetString();
- creatureTemplate.SubName = fields[8].GetString();
- creatureTemplate.TitleAlt = fields[9].GetString();
- creatureTemplate.IconName = fields[10].GetString();
- creatureTemplate.HealthScalingExpansion = fields[11].GetInt32();
- creatureTemplate.RequiredExpansion = fields[12].GetUInt32();
- creatureTemplate.VignetteID = fields[13].GetUInt32();
- creatureTemplate.faction = fields[14].GetUInt16();
- creatureTemplate.npcflag = fields[15].GetUInt64();
- creatureTemplate.speed_walk = fields[16].GetFloat();
- creatureTemplate.speed_run = fields[17].GetFloat();
- creatureTemplate.scale = fields[18].GetFloat();
- creatureTemplate.rank = uint32(fields[19].GetUInt8());
- creatureTemplate.dmgschool = uint32(fields[20].GetInt8());
- creatureTemplate.BaseAttackTime = fields[21].GetUInt32();
- creatureTemplate.RangeAttackTime = fields[22].GetUInt32();
- creatureTemplate.BaseVariance = fields[23].GetFloat();
- creatureTemplate.RangeVariance = fields[24].GetFloat();
- creatureTemplate.unit_class = uint32(fields[25].GetUInt8());
- creatureTemplate.unit_flags = fields[26].GetUInt32();
- creatureTemplate.unit_flags2 = fields[27].GetUInt32();
- creatureTemplate.unit_flags3 = fields[28].GetUInt32();
- creatureTemplate.dynamicflags = fields[29].GetUInt32();
- creatureTemplate.family = CreatureFamily(fields[30].GetInt32());
- creatureTemplate.trainer_class = uint32(fields[31].GetUInt8());
- creatureTemplate.type = uint32(fields[32].GetUInt8());
- creatureTemplate.type_flags = fields[33].GetUInt32();
- creatureTemplate.type_flags2 = fields[34].GetUInt32();
- creatureTemplate.lootid = fields[35].GetUInt32();
- creatureTemplate.pickpocketLootId = fields[36].GetUInt32();
- creatureTemplate.SkinLootId = fields[37].GetUInt32();
+ creatureTemplate.KillCredit[i] = fields[1 + i].GetUInt32();
+
+ creatureTemplate.Name = fields[3].GetString();
+ creatureTemplate.FemaleName = fields[4].GetString();
+ creatureTemplate.SubName = fields[5].GetString();
+ creatureTemplate.TitleAlt = fields[6].GetString();
+ creatureTemplate.IconName = fields[7].GetString();
+ creatureTemplate.RequiredExpansion = fields[8].GetUInt32();
+ creatureTemplate.VignetteID = fields[9].GetUInt32();
+ creatureTemplate.faction = fields[10].GetUInt16();
+ creatureTemplate.npcflag = fields[11].GetUInt64();
+ creatureTemplate.speed_walk = fields[12].GetFloat();
+ creatureTemplate.speed_run = fields[13].GetFloat();
+ creatureTemplate.scale = fields[14].GetFloat();
+ creatureTemplate.rank = uint32(fields[15].GetUInt8());
+ creatureTemplate.dmgschool = uint32(fields[16].GetInt8());
+ creatureTemplate.BaseAttackTime = fields[17].GetUInt32();
+ creatureTemplate.RangeAttackTime = fields[18].GetUInt32();
+ creatureTemplate.BaseVariance = fields[19].GetFloat();
+ creatureTemplate.RangeVariance = fields[20].GetFloat();
+ creatureTemplate.unit_class = uint32(fields[21].GetUInt8());
+ creatureTemplate.unit_flags = fields[22].GetUInt32();
+ creatureTemplate.unit_flags2 = fields[23].GetUInt32();
+ creatureTemplate.unit_flags3 = fields[24].GetUInt32();
+ creatureTemplate.dynamicflags = fields[25].GetUInt32();
+ creatureTemplate.family = CreatureFamily(fields[26].GetInt32());
+ creatureTemplate.trainer_class = uint32(fields[27].GetUInt8());
+ creatureTemplate.type = uint32(fields[28].GetUInt8());
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
creatureTemplate.resistance[i] = 0;
@@ -457,50 +448,41 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
creatureTemplate.spells[i] = 0;
- creatureTemplate.VehicleId = fields[38].GetUInt32();
- creatureTemplate.mingold = fields[39].GetUInt32();
- creatureTemplate.maxgold = fields[40].GetUInt32();
- creatureTemplate.AIName = fields[41].GetString();
- creatureTemplate.MovementType = uint32(fields[42].GetUInt8());
- if (!fields[43].IsNull())
- creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[43].GetUInt8());
-
- if (!fields[44].IsNull())
- creatureTemplate.Movement.Swim = fields[44].GetBool();
-
- if (!fields[45].IsNull())
- creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[45].GetUInt8());
-
- if (!fields[46].IsNull())
- creatureTemplate.Movement.Rooted = fields[46].GetBool();
-
- if (!fields[47].IsNull())
- creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[47].GetUInt8());
-
- if (!fields[48].IsNull())
- creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[48].GetUInt8());
-
- if (!fields[49].IsNull())
- creatureTemplate.Movement.InteractionPauseTimer = fields[49].GetUInt32();
-
- creatureTemplate.ModHealth = fields[50].GetFloat();
- creatureTemplate.ModHealthExtra = fields[51].GetFloat();
- creatureTemplate.ModMana = fields[52].GetFloat();
- creatureTemplate.ModManaExtra = fields[53].GetFloat();
- creatureTemplate.ModArmor = fields[54].GetFloat();
- creatureTemplate.ModDamage = fields[55].GetFloat();
- creatureTemplate.ModExperience = fields[56].GetFloat();
- creatureTemplate.RacialLeader = fields[57].GetBool();
- creatureTemplate.movementId = fields[58].GetUInt32();
- creatureTemplate.CreatureDifficultyID = fields[59].GetInt32();
- creatureTemplate.WidgetSetID = fields[60].GetInt32();
- creatureTemplate.WidgetSetUnitConditionID = fields[61].GetInt32();
- creatureTemplate.RegenHealth = fields[62].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[63].GetUInt64();
- creatureTemplate.SpellSchoolImmuneMask = fields[64].GetUInt32();
- creatureTemplate.flags_extra = fields[65].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[66].GetString());
- creatureTemplate.StringId = fields[67].GetString();
+ creatureTemplate.VehicleId = fields[29].GetUInt32();
+ creatureTemplate.AIName = fields[30].GetString();
+ creatureTemplate.MovementType = uint32(fields[31].GetUInt8());
+ if (!fields[32].IsNull())
+ creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[32].GetUInt8());
+
+ if (!fields[33].IsNull())
+ creatureTemplate.Movement.Swim = fields[33].GetBool();
+
+ if (!fields[34].IsNull())
+ creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[34].GetUInt8());
+
+ if (!fields[35].IsNull())
+ creatureTemplate.Movement.Rooted = fields[35].GetBool();
+
+ if (!fields[36].IsNull())
+ creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[36].GetUInt8());
+
+ if (!fields[37].IsNull())
+ creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[37].GetUInt8());
+
+ if (!fields[38].IsNull())
+ creatureTemplate.Movement.InteractionPauseTimer = fields[38].GetUInt32();
+
+ creatureTemplate.ModExperience = fields[39].GetFloat();
+ creatureTemplate.RacialLeader = fields[40].GetBool();
+ creatureTemplate.movementId = fields[41].GetUInt32();
+ creatureTemplate.WidgetSetID = fields[42].GetInt32();
+ creatureTemplate.WidgetSetUnitConditionID = fields[43].GetInt32();
+ creatureTemplate.RegenHealth = fields[44].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[45].GetUInt64();
+ creatureTemplate.SpellSchoolImmuneMask = fields[46].GetUInt32();
+ creatureTemplate.flags_extra = fields[47].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[48].GetString());
+ creatureTemplate.StringId = fields[49].GetString();
}
void ObjectMgr::LoadCreatureTemplateGossip()
@@ -935,16 +917,16 @@ void ObjectMgr::LoadCreatureTemplateSparring()
TC_LOG_INFO("server.loading", ">> Loaded %u creature template sparring rows in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadCreatureScalingData()
+void ObjectMgr::LoadCreatureTemplateDifficulty()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4
- QueryResult result = WorldDatabase.Query("SELECT Entry, DifficultyID, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID FROM creature_template_scaling ORDER BY Entry");
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
+ QueryResult result = WorldDatabase.Query("SELECT Entry, DifficultyID, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID, HealthScalingExpansion, HealthModifier, ManaModifier, ArmorModifier, DamageModifier, CreatureDifficultyID, TypeFlags, TypeFlags2, LootID, PickPocketLootID, SkinLootID, GoldMin, GoldMax FROM creature_template_difficulty ORDER BY Entry");
if (!result)
{
- TC_LOG_INFO("server.loading", ">> Loaded 0 creature template scaling definitions. DB table `creature_template_scaling` is empty.");
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creature template difficulty definitions. DB table `creature_template_difficulty` is empty.");
return;
}
@@ -959,34 +941,51 @@ void ObjectMgr::LoadCreatureScalingData()
auto itr = _creatureTemplateStore.find(entry);
if (itr == _creatureTemplateStore.end())
{
- TC_LOG_ERROR("sql.sql", "Creature template (Entry: {}) does not exist but has a record in `creature_template_scaling`", entry);
+ TC_LOG_ERROR("sql.sql", "Creature template (Entry: {}) does not exist but has a record in `creature_template_difficulty`", entry);
continue;
}
- CreatureLevelScaling creatureLevelScaling;
- creatureLevelScaling.DeltaLevelMin = fields[2].GetInt16();
- creatureLevelScaling.DeltaLevelMax = fields[3].GetInt16();
- creatureLevelScaling.ContentTuningID = fields[4].GetInt32();
+ CreatureDifficulty creatureDifficulty;
+ creatureDifficulty.DeltaLevelMin = fields[2].GetInt16();
+ creatureDifficulty.DeltaLevelMax = fields[3].GetInt16();
+ creatureDifficulty.ContentTuningID = fields[4].GetInt32();
+ creatureDifficulty.HealthScalingExpansion = fields[5].GetInt32();
+ creatureDifficulty.HealthModifier = fields[6].GetFloat();
+ creatureDifficulty.ManaModifier = fields[7].GetFloat();
+ creatureDifficulty.ArmorModifier = fields[8].GetFloat();
+ creatureDifficulty.DamageModifier = fields[9].GetFloat();
+ creatureDifficulty.CreatureDifficultyID = fields[10].GetInt32();
+ creatureDifficulty.TypeFlags = fields[11].GetUInt32();
+ creatureDifficulty.TypeFlags2 = fields[12].GetUInt32();
+ creatureDifficulty.LootID = fields[13].GetUInt32();
+ creatureDifficulty.PickPocketLootID = fields[14].GetUInt32();
+ creatureDifficulty.SkinLootID = fields[15].GetUInt32();
+ creatureDifficulty.GoldMin = fields[16].GetUInt32();
+ creatureDifficulty.GoldMax = fields[17].GetUInt32();
- itr->second.scalingStore[difficulty] = creatureLevelScaling;
+ // TODO: Check if this still applies
+ creatureDifficulty.DamageModifier *= Creature::_GetDamageMod(itr->second.rank);
- // Assign creature level scaling to creature difficulty entry (if any)
- // TODO: Drop the use of creature difficulties
- int32 difficultyIndex = CreatureTemplate::DifficultyIDToDifficultyEntryIndex(difficulty);
- if (difficultyIndex != -1)
+ if (creatureDifficulty.HealthScalingExpansion < EXPANSION_LEVEL_CURRENT || creatureDifficulty.HealthScalingExpansion >= MAX_EXPANSIONS)
{
- if (uint32 difficultyEntry = itr->second.DifficultyEntry[difficultyIndex])
- {
- auto itr2 = _creatureTemplateStore.find(difficultyEntry);
- if (itr2 != _creatureTemplateStore.end())
- itr2->second.scalingStore[difficulty] = creatureLevelScaling;
- }
+ TC_LOG_ERROR("sql.sql", "Table `creature_template_difficulty` lists creature (ID: {}) with invalid `HealthScalingExpansion` {}. Ignored and set to 0.",
+ entry, creatureDifficulty.HealthScalingExpansion);
+ creatureDifficulty.HealthScalingExpansion = 0;
}
+ if (creatureDifficulty.GoldMin > creatureDifficulty.GoldMax)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature_template_difficulty` lists creature (ID: {}) with `GoldMin` {} greater than `GoldMax` {}, setting `GoldMax` to {}.",
+ entry, creatureDifficulty.GoldMin, creatureDifficulty.GoldMax, creatureDifficulty.GoldMin);
+ creatureDifficulty.GoldMax = creatureDifficulty.GoldMin;
+ }
+
+ itr->second.difficultyStore[difficulty] = creatureDifficulty;
+
++count;
} while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded {} creature template scaling data in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded {} creature template difficulty data in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
@@ -994,183 +993,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
if (!cInfo)
return;
- bool ok = true; // bool to allow continue outside this loop
- for (uint32 diff = 0; diff < MAX_CREATURE_DIFFICULTIES && ok; ++diff)
- {
- if (!cInfo->DifficultyEntry[diff])
- continue;
- ok = false; // will be set to true at the end of this loop again
-
- CreatureTemplate const* difficultyInfo = GetCreatureTemplate(cInfo->DifficultyEntry[diff]);
- if (!difficultyInfo)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has `difficulty_entry_{}`={} but creature entry {} does not exist.",
- cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff]);
- continue;
- }
-
- bool ok2 = true;
- for (uint32 diff2 = 0; diff2 < MAX_CREATURE_DIFFICULTIES && ok2; ++diff2)
- {
- ok2 = false;
- if (_difficultyEntries[diff2].find(cInfo->Entry) != _difficultyEntries[diff2].end())
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) is listed as `difficulty_entry_{}` of another creature, but itself lists {} in `difficulty_entry_{}`.",
- cInfo->Entry, diff2 + 1, cInfo->DifficultyEntry[diff], diff + 1);
- continue;
- }
-
- if (_difficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != _difficultyEntries[diff2].end())
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) already listed as `difficulty_entry_{}` for another entry.", cInfo->DifficultyEntry[diff], diff2 + 1);
- continue;
- }
-
- if (_hasDifficultyEntries[diff2].find(cInfo->DifficultyEntry[diff]) != _hasDifficultyEntries[diff2].end())
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has `difficulty_entry_{}`={} but creature entry {} has itself a value in `difficulty_entry_{}`.",
- cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff], cInfo->DifficultyEntry[diff], diff2 + 1);
- continue;
- }
- ok2 = true;
- }
-
- if (!ok2)
- continue;
-
- if (cInfo->HealthScalingExpansion > difficultyInfo->HealthScalingExpansion)
- {
- TC_LOG_ERROR("sql.sql", "Creature (ID: {}, Expansion: {}) has different `HealthScalingExpansion` in difficulty {} mode (ID: {}, Expansion: {}).",
- cInfo->Entry, cInfo->HealthScalingExpansion, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->HealthScalingExpansion);
- }
-
- if (cInfo->faction != difficultyInfo->faction)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, faction: {}) has different `faction` in difficulty {} mode (Entry: {}, faction: {}).",
- cInfo->Entry, cInfo->faction, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->faction);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `faction`={} WHERE `entry`={};",
- cInfo->faction, cInfo->DifficultyEntry[diff]);
- }
-
- if (cInfo->unit_class != difficultyInfo->unit_class)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, class: {}) has different `unit_class` in difficulty {} mode (Entry: {}, class: {}).",
- cInfo->Entry, cInfo->unit_class, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->unit_class);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `unit_class`={} WHERE `entry`={};",
- cInfo->unit_class, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
- uint32 differenceMask = cInfo->npcflag ^ difficultyInfo->npcflag;
- if (cInfo->npcflag != difficultyInfo->npcflag)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, `npcflag`: {}) has different `npcflag` in difficulty {} mode (Entry: {}, `npcflag`: {}).",
- cInfo->Entry, cInfo->npcflag, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->npcflag);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `npcflag`=`npcflag`^{} WHERE `entry`={};",
- differenceMask, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
- if (cInfo->dmgschool != difficultyInfo->dmgschool)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, `dmgschool`: {}) has different `dmgschool` in difficulty {} mode (Entry: {}, `dmgschool`: {}).",
- cInfo->Entry, cInfo->dmgschool, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->dmgschool);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `dmgschool`={} WHERE `entry`={};",
- cInfo->dmgschool, cInfo->DifficultyEntry[diff]);
- }
-
- differenceMask = cInfo->unit_flags2 ^ difficultyInfo->unit_flags2;
- if (cInfo->unit_flags2 != difficultyInfo->unit_flags2)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, `unit_flags2`: {}) has different `unit_flags2` in difficulty {} mode (Entry: {}, `unit_flags2`: {}).",
- cInfo->Entry, cInfo->unit_flags2, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->unit_flags2);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `unit_flags2`=`unit_flags2`^{} WHERE `entry`={};",
- differenceMask, cInfo->DifficultyEntry[diff]);
- }
-
- if (cInfo->family != difficultyInfo->family)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, family: {}) has different `family` in difficulty {} mode (Entry: {}, family: {}).",
- cInfo->Entry, cInfo->family, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->family);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `family`={} WHERE `entry`={};",
- cInfo->family, cInfo->DifficultyEntry[diff]);
- }
-
- if (cInfo->trainer_class != difficultyInfo->trainer_class)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, trainer_class: {}) has different `trainer_class` in difficulty {} mode (Entry: {}, trainer_class: {}).",
- cInfo->Entry, cInfo->trainer_class, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->trainer_class);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `trainer_class`={} WHERE `entry`={};",
- cInfo->trainer_class, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
- if (cInfo->type != difficultyInfo->type)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, type: {}) has different `type` in difficulty {} mode (Entry: {}, type: {}).",
- cInfo->Entry, cInfo->type, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `type`={} WHERE `entry`={};",
- cInfo->type, cInfo->DifficultyEntry[diff]);
- }
-
- if (!cInfo->VehicleId && difficultyInfo->VehicleId)
- {
- TC_LOG_ERROR("sql.sql", "Non-vehicle Creature (Entry: {}, VehicleId: {}) has `VehicleId` set in difficulty {} mode (Entry: {}, VehicleId: {}).",
- cInfo->Entry, cInfo->VehicleId, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->VehicleId);
- }
-
- if (cInfo->RegenHealth != difficultyInfo->RegenHealth)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, RegenHealth: {}) has different `RegenHealth` in difficulty {} mode (Entry: {}, RegenHealth: {}).",
- cInfo->Entry, cInfo->RegenHealth, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->RegenHealth);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `RegenHealth`={} WHERE `entry`={};",
- cInfo->RegenHealth, cInfo->DifficultyEntry[diff]);
- }
-
- differenceMask = cInfo->MechanicImmuneMask & (~difficultyInfo->MechanicImmuneMask);
- if (differenceMask)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, mechanic_immune_mask: {}) has weaker immunities in difficulty {} mode (Entry: {}, mechanic_immune_mask: {}).",
- cInfo->Entry, cInfo->MechanicImmuneMask, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->MechanicImmuneMask);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `mechanic_immune_mask`=`mechanic_immune_mask`|{} WHERE `entry`={};",
- differenceMask, cInfo->DifficultyEntry[diff]);
- }
-
- differenceMask = (cInfo->flags_extra ^ difficultyInfo->flags_extra) & (~CREATURE_FLAG_EXTRA_INSTANCE_BIND);
- if (differenceMask)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}, flags_extra: {}) has different `flags_extra` in difficulty {} mode (Entry: {}, flags_extra: {}).",
- cInfo->Entry, cInfo->flags_extra, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->flags_extra);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `flags_extra`=`flags_extra`^{} WHERE `entry`={};",
- differenceMask, cInfo->DifficultyEntry[diff]);
- }
-
- if (!difficultyInfo->AIName.empty())
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) lists difficulty {} mode entry {} with `AIName` filled in. `AIName` of difficulty 0 mode creature is always used instead.",
- cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
- if (difficultyInfo->ScriptID)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) lists difficulty {} mode entry {} with `ScriptName` filled in. `ScriptName` of difficulty 0 mode creature is always used instead.",
- cInfo->Entry, diff + 1, cInfo->DifficultyEntry[diff]);
- continue;
- }
-
- _hasDifficultyEntries[diff].insert(cInfo->Entry);
- _difficultyEntries[diff].insert(cInfo->DifficultyEntry[diff]);
- ok = true;
- }
-
- if (cInfo->mingold > cInfo->maxgold)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has `mingold` {} which is greater than `maxgold` {}, setting `maxgold` to {}.",
- cInfo->Entry, cInfo->mingold, cInfo->maxgold, cInfo->mingold);
- const_cast<CreatureTemplate*>(cInfo)->maxgold = cInfo->mingold;
- }
-
if (!cInfo->AIName.empty())
{
auto registryItem = sCreatureAIRegistry->GetRegistryItem(cInfo->AIName);
@@ -1281,12 +1103,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
}
- if (cInfo->HealthScalingExpansion < EXPANSION_LEVEL_CURRENT || cInfo->HealthScalingExpansion >= MAX_EXPANSIONS)
- {
- TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (ID: {}) with invalid `HealthScalingExpansion` {}. Ignored and set to 0.", cInfo->Entry, cInfo->HealthScalingExpansion);
- const_cast<CreatureTemplate*>(cInfo)->HealthScalingExpansion = 0;
- }
-
if (cInfo->RequiredExpansion >= MAX_EXPANSIONS)
{
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: {}) with `RequiredExpansion` {}. Ignored and set to 0.", cInfo->Entry, cInfo->RequiredExpansion);
@@ -1323,8 +1139,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->dynamicflags = 0;
}
- const_cast<CreatureTemplate*>(cInfo)->ModDamage *= Creature::_GetDamageMod(cInfo->rank);
-
if (!cInfo->GossipMenuIds.empty() && !(cInfo->npcflag & UNIT_NPC_FLAG_GOSSIP))
TC_LOG_INFO("sql.sql", "Creature (Entry: {}) has assigned gossip menu, but npcflag does not include UNIT_NPC_FLAG_GOSSIP.", cInfo->Entry);
else if (cInfo->GossipMenuIds.empty() && cInfo->npcflag & UNIT_NPC_FLAG_GOSSIP)
@@ -2412,19 +2226,6 @@ void ObjectMgr::LoadCreatures()
continue;
}
- bool ok = true;
- for (uint32 diff = 0; diff < MAX_CREATURE_DIFFICULTIES && ok; ++diff)
- {
- if (_difficultyEntries[diff].find(data.id) != _difficultyEntries[diff].end())
- {
- TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: {}) that is listed as difficulty {} template (entry: {}) in `creature_template`, skipped.",
- guid, diff + 1, data.id);
- ok = false;
- }
- }
- if (!ok)
- continue;
-
// -1 random, 0 no equipment
if (data.equipmentId != 0)
{
@@ -4635,6 +4436,20 @@ void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, Play
}
}
+std::vector<uint32> const* ObjectMgr::GetCreatureQuestItemList(uint32 creatureEntry, Difficulty difficulty) const
+{
+ CreatureQuestItemMap::const_iterator itr = _creatureQuestItemStore.find(std::make_pair(creatureEntry, difficulty));
+ if (itr != _creatureQuestItemStore.end())
+ return &itr->second;
+
+ // If there is no data for the difficulty, try to get data for the fallback difficulty
+ DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
+ if (difficultyEntry)
+ return GetCreatureQuestItemList(creatureEntry, Difficulty(difficultyEntry->FallbackDifficultyID));
+
+ return nullptr;
+}
+
void ObjectMgr::LoadQuests()
{
uint32 oldMSTime = getMSTime();
@@ -6442,14 +6257,6 @@ void ObjectMgr::LoadInstanceEncounters()
continue;
}
const_cast<CreatureTemplate*>(creatureInfo)->flags_extra |= CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
- for (uint8 diff = 0; diff < MAX_CREATURE_DIFFICULTIES; ++diff)
- {
- if (uint32 diffEntry = creatureInfo->DifficultyEntry[diff])
- {
- if (CreatureTemplate const* diffInfo = GetCreatureTemplate(diffEntry))
- const_cast<CreatureTemplate*>(diffInfo)->flags_extra |= CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
- }
- }
break;
}
case ENCOUNTER_CREDIT_CAST_SPELL:
@@ -10993,8 +10800,8 @@ void ObjectMgr::LoadCreatureQuestItems()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT CreatureEntry, ItemId, Idx FROM creature_questitem ORDER BY Idx ASC");
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT CreatureEntry, DifficultyID, ItemId, Idx FROM creature_questitem ORDER BY Idx ASC");
if (!result)
{
@@ -11008,24 +10815,25 @@ void ObjectMgr::LoadCreatureQuestItems()
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
- uint32 item = fields[1].GetUInt32();
- uint32 idx = fields[2].GetUInt32();
+ Difficulty difficulty = Difficulty(fields[1].GetUInt8());
+ uint32 item = fields[2].GetUInt32();
+ uint32 idx = fields[3].GetUInt32();
CreatureTemplate const* creatureInfo = GetCreatureTemplate(entry);
if (!creatureInfo)
{
- TC_LOG_ERROR("sql.sql", "Table `creature_questitem` has data for nonexistent creature (entry: {}, idx: {}), skipped", entry, idx);
+ TC_LOG_ERROR("sql.sql", "Table `creature_questitem` has data for nonexistent creature (entry: {}, difficulty: {}, idx: {}), skipped", entry, difficulty, idx);
continue;
};
ItemEntry const* db2Data = sItemStore.LookupEntry(item);
if (!db2Data)
{
- TC_LOG_ERROR("sql.sql", "Table `creature_questitem` has nonexistent item (ID: {}) in creature (entry: {}, idx: {}), skipped", item, entry, idx);
+ TC_LOG_ERROR("sql.sql", "Table `creature_questitem` has nonexistent item (ID: {}) in creature (entry: {}, difficulty: {}, idx: {}), skipped", item, entry, difficulty, idx);
continue;
};
- _creatureQuestItemStore[entry].push_back(item);
+ _creatureQuestItemStore[std::make_pair(entry, difficulty)].push_back(item);
++count;
}