diff options
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 466 |
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; } |