aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTraesh <Traesh@users.noreply.github.com>2018-11-07 20:23:30 +0100
committerShauren <shauren.trinity@gmail.com>2018-11-07 20:23:30 +0100
commit9d210476e57949094fdd286001ef4900564edca5 (patch)
tree1e8ed5d261698e633ee3371779d30f8c1666526e
parent31f0186d20a1944e5d0ff47d71ca8f560074de4b (diff)
Core/Creatures: Update creature model handling with new display scale (#22567)
-rw-r--r--sql/updates/world/master/2018_11_05_00_world.sql23
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp8
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp144
-rw-r--r--src/server/game/Entities/Creature/Creature.h3
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h31
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp4
-rw-r--r--src/server/game/Entities/Pet/Pet.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp8
-rw-r--r--src/server/game/Entities/Unit/Unit.h5
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp320
-rw-r--r--src/server/game/Globals/ObjectMgr.h5
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp20
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp13
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp5
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp1
-rw-r--r--src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp2
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp6
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp6
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp2
-rw-r--r--src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp10
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp2
-rw-r--r--src/server/scripts/World/npcs_special.cpp4
32 files changed, 340 insertions, 306 deletions
diff --git a/sql/updates/world/master/2018_11_05_00_world.sql b/sql/updates/world/master/2018_11_05_00_world.sql
new file mode 100644
index 00000000000..934627d98fb
--- /dev/null
+++ b/sql/updates/world/master/2018_11_05_00_world.sql
@@ -0,0 +1,23 @@
+DROP TABLE IF EXISTS `creature_template_model`;
+CREATE TABLE `creature_template_model`(
+ `CreatureID` int(10) unsigned NOT NULL,
+ `Idx` int(10) unsigned NOT NULL DEFAULT '0',
+ `CreatureDisplayID` int(10) unsigned NOT NULL,
+ `DisplayScale` float NOT NULL DEFAULT '1',
+ `Probability` float NOT NULL DEFAULT '0',
+ `VerifiedBuild` smallint(5) unsigned NOT NULL,
+ PRIMARY KEY (`CreatureID`,`CreatureDisplayID`)
+) ENGINE=MYISAM CHARSET=utf8mb4;
+
+INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,0,`modelid1`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid1`!=0;
+INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,1,`modelid2`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid2`!=0;
+INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,2,`modelid3`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid3`!=0;
+INSERT IGNORE INTO `creature_template_model` (`CreatureID`,`Idx`,`CreatureDisplayID`,`DisplayScale`,`Probability`,`VerifiedBuild`) SELECT `entry`,3,`modelid4`,`scale`,1,`VerifiedBuild` FROM `creature_template` WHERE `modelid4`!=0;
+
+UPDATE `creature_template` SET `scale`=1;
+
+ALTER TABLE `creature_template`
+ DROP `modelid1`,
+ DROP `modelid2`,
+ DROP `modelid3`,
+ DROP `modelid4`;
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index 01cb3023c29..a66132121a9 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, rank, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, rank, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 79af3ea66b9..17851adc4de 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -412,10 +412,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
{
if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature))
{
- uint32 displayId = ObjectMgr::ChooseDisplayId(ci);
- (*itr)->ToCreature()->SetDisplayId(displayId);
+ CreatureModel const* model = ObjectMgr::ChooseDisplayId(ci);
+ (*itr)->ToCreature()->SetDisplayId(model->CreatureDisplayID, model->DisplayScale);
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry %u, %s set displayid to %u",
- (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str(), displayId);
+ (*itr)->GetEntry(), (*itr)->GetGUID().ToString().c_str(), model->CreatureDisplayID);
}
}
//if no param1, then use value from param2 (modelId)
@@ -1291,7 +1291,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.action.morphOrMount.creature > 0)
{
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature))
- (*itr)->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo));
+ (*itr)->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)->CreatureDisplayID);
}
else
(*itr)->ToUnit()->Mount(e.action.morphOrMount.model);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index b6d6e44a3fe..f521cdfd3b0 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -77,68 +77,67 @@ VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extend
return nullptr;
}
-uint32 CreatureTemplate::GetRandomValidModelId() const
-{
- uint8 c = 0;
- uint32 modelIDs[4];
-
- if (Modelid1) modelIDs[c++] = Modelid1;
- if (Modelid2) modelIDs[c++] = Modelid2;
- if (Modelid3) modelIDs[c++] = Modelid3;
- if (Modelid4) modelIDs[c++] = Modelid4;
+CreatureModel const CreatureModel::DefaultInvisibleModel(11686, 1.0f, 1.0f);
+CreatureModel const CreatureModel::DefaultVisibleModel(17519, 1.0f, 1.0f);
- return ((c>0) ? modelIDs[urand(0, c-1)] : 0);
-}
-
-uint32 CreatureTemplate::GetFirstValidModelId() const
+CreatureModel const* CreatureTemplate::GetModelByIdx(uint32 idx) const
{
- if (Modelid1) return Modelid1;
- if (Modelid2) return Modelid2;
- if (Modelid3) return Modelid3;
- if (Modelid4) return Modelid4;
- return 0;
+ return idx < Models.size() ? &Models[idx] : nullptr;
}
-uint32 CreatureTemplate::GetFirstInvisibleModel() const
+CreatureModel const* CreatureTemplate::GetRandomValidModel() const
{
- CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid1);
- if (modelInfo && modelInfo->is_trigger)
- return Modelid1;
+ if (!Models.size())
+ return nullptr;
- modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid2);
- if (modelInfo && modelInfo->is_trigger)
- return Modelid2;
+ // If only one element, ignore the Probability (even if 0)
+ if (Models.size() == 1)
+ return &Models[0];
- modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid3);
- if (modelInfo && modelInfo->is_trigger)
- return Modelid3;
+ auto selectedItr = Trinity::Containers::SelectRandomWeightedContainerElement(Models, [](CreatureModel const& model)
+ {
+ return model.Probability;
+ });
- modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid4);
- if (modelInfo && modelInfo->is_trigger)
- return Modelid4;
+ return &(*selectedItr);
+}
+
+CreatureModel const* CreatureTemplate::GetFirstValidModel() const
+{
+ for (CreatureModel const& model : Models)
+ if (model.CreatureDisplayID)
+ return &model;
- return 11686;
+ return nullptr;
}
-uint32 CreatureTemplate::GetFirstVisibleModel() const
+CreatureModel const* CreatureTemplate::GetModelWithDisplayId(uint32 displayId) const
{
- CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid1);
- if (modelInfo && !modelInfo->is_trigger)
- return Modelid1;
+ for (CreatureModel const& model : Models)
+ if (displayId == model.CreatureDisplayID)
+ return &model;
- modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid2);
- if (modelInfo && !modelInfo->is_trigger)
- return Modelid2;
+ return nullptr;
+}
+
+CreatureModel const* CreatureTemplate::GetFirstInvisibleModel() const
+{
+ for (CreatureModel const& model : Models)
+ if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID))
+ if (modelInfo && modelInfo->is_trigger)
+ return &model;
- modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid3);
- if (modelInfo && !modelInfo->is_trigger)
- return Modelid3;
+ return &CreatureModel::DefaultInvisibleModel;
+}
- modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid4);
- if (modelInfo && !modelInfo->is_trigger)
- return Modelid4;
+CreatureModel const* CreatureTemplate::GetFirstVisibleModel() const
+{
+ for (CreatureModel const& model : Models)
+ if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID))
+ if (modelInfo && !modelInfo->is_trigger)
+ return &model;
- return 17519;
+ return &CreatureModel::DefaultVisibleModel;
}
bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
@@ -343,22 +342,22 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(cinfo->unit_class));
// Cancel load if no model defined
- if (!(cinfo->GetFirstValidModelId()))
+ if (!(cinfo->GetFirstValidModel()))
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has no model defined in table `creature_template`, can't load. ", entry);
return false;
}
- uint32 displayID = ObjectMgr::ChooseDisplayId(GetCreatureTemplate(), data);
- CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID);
+ CreatureModel model = *ObjectMgr::ChooseDisplayId(cinfo, data);
+ CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&model, cinfo);
if (!minfo) // Cancel load if no model defined
{
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid model %u defined in table `creature_template`, can't load.", entry, displayID);
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid model %u defined in table `creature_template`, can't load.", entry, model.CreatureDisplayID);
return false;
}
- SetDisplayId(displayID);
- SetNativeDisplayId(displayID);
+ SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
+ SetNativeDisplayId(model.CreatureDisplayID, model.DisplayScale);
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
// Load creature equipment
@@ -384,7 +383,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetSpeedRate(MOVE_SWIM, 1.0f); // using 1.0 rate
SetSpeedRate(MOVE_FLIGHT, 1.0f); // using 1.0 rate
- // Will set UNIT_FIELD_BOUNDINGRADIUS and UNIT_FIELD_COMBATREACH
+ // Will set UNIT_FIELD_BOUNDINGRADIUS, UNIT_FIELD_COMBATREACH and UNIT_FIELD_DISPLAYSCALE
SetObjectScale(cinfo->scale);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, cinfo->HoverHeight);
@@ -892,7 +891,8 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float
if (!CreateFromProto(guidlow, entry, data, vehId))
return false;
- switch (GetCreatureTemplate()->rank)
+ cinfo = GetCreatureTemplate(); // might be different than initially requested
+ switch (cinfo->rank)
{
case CREATURE_ELITE_RARE:
m_corpseDelay = sWorld->getIntConfig(CONFIG_CORPSE_DECAY_RARE);
@@ -922,12 +922,12 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float
Relocate(x, y, z, ang);
}
- uint32 displayID = GetNativeDisplayId();
- CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID);
+ CreatureModel display(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f);
+ CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, cinfo);
if (minfo && !IsTotem()) // Cancel load if no model defined or if totem
{
- SetDisplayId(displayID);
- SetNativeDisplayId(displayID);
+ SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
+ SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
}
@@ -940,10 +940,10 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST);
}
- if (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING)
+ if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING)
AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
- if (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK)
+ if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK)
{
ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, true);
@@ -1127,9 +1127,9 @@ void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDiffic
CreatureTemplate const* cinfo = GetCreatureTemplate();
if (cinfo)
{
- if (displayId == cinfo->Modelid1 || displayId == cinfo->Modelid2 ||
- displayId == cinfo->Modelid3 || displayId == cinfo->Modelid4)
- displayId = 0;
+ for (CreatureModel model : cinfo->Models)
+ if (displayId && displayId == model.CreatureDisplayID)
+ displayId = 0;
if (npcflag == cinfo->npcflag)
npcflag = 0;
@@ -1842,12 +1842,12 @@ void Creature::Respawn(bool force)
setDeathState(JUST_RESPAWNED);
- uint32 displayID = GetNativeDisplayId();
- CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID);
+ CreatureModel display(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f);
+ CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, GetCreatureTemplate());
if (minfo) // Cancel load if no model defined
{
- SetDisplayId(displayID);
- SetNativeDisplayId(displayID);
+ SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
+ SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
}
@@ -2847,9 +2847,9 @@ void Creature::SetObjectScale(float scale)
}
}
-void Creature::SetDisplayId(uint32 modelId)
+void Creature::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/)
{
- Unit::SetDisplayId(modelId);
+ Unit::SetDisplayId(modelId, displayScale);
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
{
@@ -2858,6 +2858,12 @@ void Creature::SetDisplayId(uint32 modelId)
}
}
+void Creature::SetDisplayFromModel(uint32 modelIdx)
+{
+ if (CreatureModel const* model = GetCreatureTemplate()->GetModelByIdx(modelIdx))
+ SetDisplayId(model->CreatureDisplayID, model->DisplayScale);
+}
+
void Creature::SetTarget(ObjectGuid const& guid)
{
if (IsFocusing(nullptr, true))
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 90c84fb843a..b56fe8c9137 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -69,7 +69,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void RemoveFromWorld() override;
void SetObjectScale(float scale) override;
- void SetDisplayId(uint32 modelId) override;
+ void SetDisplayId(uint32 displayId, float displayScale = 1.f) override;
+ void SetDisplayFromModel(uint32 modelIdx);
void DisappearAndDie();
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 45a13c6f603..813aaa27e27 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -300,16 +300,29 @@ struct CreatureLevelScaling
int16 DeltaLevelMax;
};
+struct CreatureModel
+{
+ static CreatureModel const DefaultInvisibleModel;
+ static CreatureModel const DefaultVisibleModel;
+
+ CreatureModel() :
+ CreatureDisplayID(0), DisplayScale(0.0f), Probability(0.0f) { }
+
+ CreatureModel(uint32 creatureDisplayID, float displayScale, float probability) :
+ CreatureDisplayID(creatureDisplayID), DisplayScale(displayScale), Probability(probability) { }
+
+ uint32 CreatureDisplayID;
+ float DisplayScale;
+ float Probability;
+};
+
// from `creature_template` table
struct TC_GAME_API CreatureTemplate
{
uint32 Entry;
uint32 DifficultyEntry[MAX_CREATURE_DIFFICULTIES];
uint32 KillCredit[MAX_KILL_CREDIT];
- uint32 Modelid1;
- uint32 Modelid2;
- uint32 Modelid3;
- uint32 Modelid4;
+ std::vector<CreatureModel> Models;
std::string Name;
std::string FemaleName;
std::string SubName;
@@ -368,10 +381,12 @@ struct TC_GAME_API CreatureTemplate
uint32 MechanicImmuneMask;
uint32 flags_extra;
uint32 ScriptID;
- uint32 GetRandomValidModelId() const;
- uint32 GetFirstValidModelId() const;
- uint32 GetFirstInvisibleModel() const;
- uint32 GetFirstVisibleModel() const;
+ CreatureModel const* GetModelByIdx(uint32 idx) const;
+ CreatureModel const* GetRandomValidModel() const;
+ CreatureModel const* GetFirstValidModel() const;
+ CreatureModel const* GetModelWithDisplayId(uint32 displayId) const;
+ CreatureModel const* GetFirstInvisibleModel() const;
+ CreatureModel const* GetFirstVisibleModel() const;
// helpers
SkillType GetRequiredLootSkill() const
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 67fa6c00554..d8ab46e6b07 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -1778,9 +1778,9 @@ Player* Pet::GetOwner() const
return Minion::GetOwner()->ToPlayer();
}
-void Pet::SetDisplayId(uint32 modelId)
+void Pet::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/)
{
- Guardian::SetDisplayId(modelId);
+ Guardian::SetDisplayId(modelId, displayScale);
if (!isControlled())
return;
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index e411d2251af..f82c88e6b44 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -52,7 +52,7 @@ class TC_GAME_API Pet : public Guardian
void AddToWorld() override;
void RemoveFromWorld() override;
- void SetDisplayId(uint32 modelId) override;
+ void SetDisplayId(uint32 modelId, float displayScale = 1.f) override;
PetType getPetType() const { return m_petType; }
void setPetType(PetType type) { m_petType = type; }
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index bb6a3e9dc5d..87d8bad3de6 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -10317,9 +10317,11 @@ bool Unit::IsPolymorphed() const
return spellInfo->GetSpellSpecific() == SPELL_SPECIFIC_MAGE_POLYMORPH;
}
-void Unit::SetDisplayId(uint32 modelId)
+void Unit::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/)
{
SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId);
+ SetFloatValue(UNIT_FIELD_DISPLAY_SCALE, displayScale);
+
// Set Gender by modelId
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
@@ -10342,7 +10344,7 @@ void Unit::RestoreDisplayId(bool ignorePositiveAurasPreventingMounting /*= false
if (!ignorePositiveAurasPreventingMounting)
handledAura = (*i);
else if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate((*i)->GetMiscValue()))
- if (!IsDisallowedMountForm((*i)->GetId(), FORM_NONE, sObjectMgr->ChooseDisplayId(ci)))
+ if (!IsDisallowedMountForm((*i)->GetId(), FORM_NONE, ObjectMgr::ChooseDisplayId(ci)->CreatureDisplayID))
handledAura = (*i);
}
// prefer negative auras
@@ -13732,7 +13734,7 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
if (target->IsGameMaster())
- displayId = cinfo->GetFirstVisibleModel();
+ displayId = cinfo->GetFirstVisibleModel()->CreatureDisplayID;
}
*data << uint32(displayId);
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 77e23462cd8..ad8ecf37733 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1684,10 +1684,11 @@ class TC_GAME_API Unit : public WorldObject
void UpdateInterruptMask();
uint32 GetDisplayId() const { return GetUInt32Value(UNIT_FIELD_DISPLAYID); }
- virtual void SetDisplayId(uint32 modelId);
+ virtual void SetDisplayId(uint32 modelId, float displayScale = 1.f);
uint32 GetNativeDisplayId() const { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }
+ float GetNativeDisplayScale() const { return GetFloatValue(UNIT_FIELD_NATIVE_X_DISPLAY_SCALE); }
void RestoreDisplayId(bool ignorePositiveAurasPreventingMounting = false);
- void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); }
+ void SetNativeDisplayId(uint32 displayId, float displayScale = 1.f) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, displayId); SetFloatValue(UNIT_FIELD_NATIVE_X_DISPLAY_SCALE, displayScale); }
void setTransForm(uint32 spellid) { m_transform = spellid;}
uint32 getTransForm() const { return m_transform;}
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index af49f29b3c1..78d7d263755 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -54,6 +54,7 @@
#include "VMapFactory.h"
#include "World.h"
#include <G3D/g3dmath.h>
+#include <numeric>
ScriptMapMap sSpellScripts;
ScriptMapMap sEventScripts;
@@ -411,21 +412,21 @@ void ObjectMgr::LoadCreatureTemplates()
{
uint32 oldMSTime = getMSTime();
- // 0 1 2 3 4 5 6 7 8
- QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, "
- // 9 10 11 12 13 14 15 16 17 18 19 20
- "modelid4, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, "
- // 21 22 23 24 25 26 27 28 29 30 31
+ // 0 1 2 3 4 5 6 7 8
+ QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, "
+ // 9 10 11 12 13 14 15 16
+ "TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, "
+ // 17 18 19 20 21 22 23 24 25 26 27
"faction, npcflag, speed_walk, speed_run, scale, rank, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, "
- // 32 33 34 35 36 37 38 39
+ // 28 29 30 31 32 33 34 35
"unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, "
- // 40 41 42 43 44 45 46 47 48 49 50
+ // 36 37 38 39 40 41 42 43 44 45 46
"type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, "
- // 51 52 53 54 55 56 57 58 59 60 61 62 63
+ // 47 48 49 50 51 52 53 54 55 56 57 58 59
"spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, "
- // 64 65 66 67 68 69 70 71 72
+ // 60 61 62 63 64 65 66 67 68
"InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, "
- // 73 74 75 76 77 78
+ // 69 70 71 72 73 74
"RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template");
if (!result)
@@ -442,6 +443,9 @@ void ObjectMgr::LoadCreatureTemplates()
}
while (result->NextRow());
+ // We load the creature models after loading but before checking
+ LoadCreatureTemplateModels();
+
// Checking needs to be done after loading because of the difficulty self referencing
for (CreatureTemplateContainer::const_iterator itr = _creatureTemplateStore.begin(); itr != _creatureTemplateStore.end(); ++itr)
CheckCreatureTemplate(&itr->second);
@@ -463,72 +467,121 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
for (uint8 i = 0; i < MAX_KILL_CREDIT; ++i)
creatureTemplate.KillCredit[i] = fields[4 + i].GetUInt32();
- creatureTemplate.Modelid1 = fields[6].GetUInt32();
- creatureTemplate.Modelid2 = fields[7].GetUInt32();
- creatureTemplate.Modelid3 = fields[8].GetUInt32();
- creatureTemplate.Modelid4 = fields[9].GetUInt32();
- creatureTemplate.Name = fields[10].GetString();
- creatureTemplate.FemaleName = fields[11].GetString();
- creatureTemplate.SubName = fields[12].GetString();
- creatureTemplate.TitleAlt = fields[13].GetString();
- creatureTemplate.IconName = fields[14].GetString();
- creatureTemplate.GossipMenuId = fields[15].GetUInt32();
- creatureTemplate.minlevel = fields[16].GetInt16();
- creatureTemplate.maxlevel = fields[17].GetInt16();
- creatureTemplate.HealthScalingExpansion = fields[18].GetInt32();
- creatureTemplate.RequiredExpansion = fields[19].GetUInt32();
- creatureTemplate.VignetteID = fields[20].GetUInt32();
- creatureTemplate.faction = fields[21].GetUInt16();
- creatureTemplate.npcflag = fields[22].GetUInt64();
- creatureTemplate.speed_walk = fields[23].GetFloat();
- creatureTemplate.speed_run = fields[24].GetFloat();
- creatureTemplate.scale = fields[25].GetFloat();
- creatureTemplate.rank = uint32(fields[26].GetUInt8());
- creatureTemplate.dmgschool = uint32(fields[27].GetInt8());
- creatureTemplate.BaseAttackTime = fields[28].GetUInt32();
- creatureTemplate.RangeAttackTime = fields[29].GetUInt32();
- creatureTemplate.BaseVariance = fields[30].GetFloat();
- creatureTemplate.RangeVariance = fields[31].GetFloat();
- creatureTemplate.unit_class = uint32(fields[32].GetUInt8());
- creatureTemplate.unit_flags = fields[33].GetUInt32();
- creatureTemplate.unit_flags2 = fields[34].GetUInt32();
- creatureTemplate.unit_flags3 = fields[35].GetUInt32();
- creatureTemplate.dynamicflags = fields[36].GetUInt32();
- creatureTemplate.family = CreatureFamily(fields[37].GetUInt8());
- creatureTemplate.trainer_class = uint32(fields[38].GetUInt8());
- creatureTemplate.type = uint32(fields[39].GetUInt8());
- creatureTemplate.type_flags = fields[40].GetUInt32();
- creatureTemplate.type_flags2 = fields[41].GetUInt32();
- creatureTemplate.lootid = fields[42].GetUInt32();
- creatureTemplate.pickpocketLootId = fields[43].GetUInt32();
- creatureTemplate.SkinLootId = fields[44].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.GossipMenuId = fields[11].GetUInt32();
+ creatureTemplate.minlevel = fields[12].GetInt16();
+ creatureTemplate.maxlevel = fields[13].GetInt16();
+ creatureTemplate.HealthScalingExpansion = fields[14].GetInt32();
+ creatureTemplate.RequiredExpansion = fields[15].GetUInt32();
+ creatureTemplate.VignetteID = fields[16].GetUInt32();
+ creatureTemplate.faction = fields[17].GetUInt16();
+ creatureTemplate.npcflag = fields[18].GetUInt64();
+ creatureTemplate.speed_walk = fields[19].GetFloat();
+ creatureTemplate.speed_run = fields[20].GetFloat();
+ creatureTemplate.scale = fields[21].GetFloat();
+ creatureTemplate.rank = uint32(fields[22].GetUInt8());
+ creatureTemplate.dmgschool = uint32(fields[23].GetInt8());
+ creatureTemplate.BaseAttackTime = fields[24].GetUInt32();
+ creatureTemplate.RangeAttackTime = fields[25].GetUInt32();
+ creatureTemplate.BaseVariance = fields[26].GetFloat();
+ creatureTemplate.RangeVariance = fields[27].GetFloat();
+ creatureTemplate.unit_class = uint32(fields[28].GetUInt8());
+ creatureTemplate.unit_flags = fields[29].GetUInt32();
+ creatureTemplate.unit_flags2 = fields[30].GetUInt32();
+ creatureTemplate.unit_flags3 = fields[31].GetUInt32();
+ creatureTemplate.dynamicflags = fields[32].GetUInt32();
+ creatureTemplate.family = CreatureFamily(fields[33].GetUInt8());
+ creatureTemplate.trainer_class = uint32(fields[34].GetUInt8());
+ creatureTemplate.type = uint32(fields[35].GetUInt8());
+ creatureTemplate.type_flags = fields[36].GetUInt32();
+ creatureTemplate.type_flags2 = fields[37].GetUInt32();
+ creatureTemplate.lootid = fields[38].GetUInt32();
+ creatureTemplate.pickpocketLootId = fields[39].GetUInt32();
+ creatureTemplate.SkinLootId = fields[40].GetUInt32();
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
- creatureTemplate.resistance[i] = fields[45 + i - 1].GetInt16();
+ creatureTemplate.resistance[i] = fields[41 + i - 1].GetInt16();
for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
- creatureTemplate.spells[i] = fields[51 + i].GetUInt32();
-
- creatureTemplate.VehicleId = fields[59].GetUInt32();
- creatureTemplate.mingold = fields[60].GetUInt32();
- creatureTemplate.maxgold = fields[61].GetUInt32();
- creatureTemplate.AIName = fields[62].GetString();
- creatureTemplate.MovementType = uint32(fields[63].GetUInt8());
- creatureTemplate.InhabitType = uint32(fields[64].GetUInt8());
- creatureTemplate.HoverHeight = fields[65].GetFloat();
- creatureTemplate.ModHealth = fields[66].GetFloat();
- creatureTemplate.ModHealthExtra = fields[67].GetFloat();
- creatureTemplate.ModMana = fields[68].GetFloat();
- creatureTemplate.ModManaExtra = fields[69].GetFloat();
- creatureTemplate.ModArmor = fields[70].GetFloat();
- creatureTemplate.ModDamage = fields[71].GetFloat();
- creatureTemplate.ModExperience = fields[72].GetFloat();
- creatureTemplate.RacialLeader = fields[73].GetBool();
- creatureTemplate.movementId = fields[74].GetUInt32();
- creatureTemplate.RegenHealth = fields[75].GetBool();
- creatureTemplate.MechanicImmuneMask = fields[76].GetUInt32();
- creatureTemplate.flags_extra = fields[77].GetUInt32();
- creatureTemplate.ScriptID = GetScriptId(fields[78].GetString());
+ creatureTemplate.spells[i] = fields[47 + i].GetUInt32();
+
+ creatureTemplate.VehicleId = fields[55].GetUInt32();
+ creatureTemplate.mingold = fields[56].GetUInt32();
+ creatureTemplate.maxgold = fields[57].GetUInt32();
+ creatureTemplate.AIName = fields[58].GetString();
+ creatureTemplate.MovementType = uint32(fields[59].GetUInt8());
+ creatureTemplate.InhabitType = uint32(fields[60].GetUInt8());
+ creatureTemplate.HoverHeight = fields[61].GetFloat();
+ creatureTemplate.ModHealth = fields[62].GetFloat();
+ creatureTemplate.ModHealthExtra = fields[63].GetFloat();
+ creatureTemplate.ModMana = fields[64].GetFloat();
+ creatureTemplate.ModManaExtra = fields[65].GetFloat();
+ creatureTemplate.ModArmor = fields[66].GetFloat();
+ creatureTemplate.ModDamage = fields[67].GetFloat();
+ creatureTemplate.ModExperience = fields[68].GetFloat();
+ creatureTemplate.RacialLeader = fields[69].GetBool();
+ creatureTemplate.movementId = fields[70].GetUInt32();
+ creatureTemplate.RegenHealth = fields[71].GetBool();
+ creatureTemplate.MechanicImmuneMask = fields[72].GetUInt32();
+ creatureTemplate.flags_extra = fields[73].GetUInt32();
+ creatureTemplate.ScriptID = GetScriptId(fields[74].GetString());
+}
+
+void ObjectMgr::LoadCreatureTemplateModels()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT CreatureID, CreatureDisplayID, DisplayScale, Probability FROM creature_template_model ORDER BY Idx ASC");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 creature template model definitions. DB table `creature_template_model` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 creatureId = fields[0].GetUInt32();
+ uint32 creatureDisplayId = fields[1].GetUInt32();
+ float displayScale = fields[2].GetFloat();
+ float probability = fields[3].GetFloat();
+
+ CreatureTemplate const* cInfo = GetCreatureTemplate(creatureId);
+ if (!cInfo)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_template_model`", creatureId);
+ continue;
+ }
+
+ CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(creatureDisplayId);
+ if (!displayEntry)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing CreatureDisplayID id (%u), this can crash the client.", creatureId, creatureDisplayId);
+ continue;
+ }
+
+ CreatureModelInfo const* modelInfo = GetCreatureModelInfo(creatureDisplayId);
+ if (!modelInfo)
+ TC_LOG_ERROR("sql.sql", "No model data exist for `CreatureDisplayID` = %u listed by creature (Entry: %u).", creatureDisplayId, creatureId);
+
+ if (displayScale <= 0.0f)
+ displayScale = 1.0f;
+
+ const_cast<CreatureTemplate*>(cInfo)->Models.emplace_back(creatureDisplayId, displayScale, probability);
+
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u creature template models in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadCreatureTemplateAddons()
@@ -867,76 +920,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->faction = sFactionTemplateStore.AssertEntry(35)->ID; // this might seem stupid but all shit will would break if faction 35 did not exist
}
- // used later for scale
- CreatureDisplayInfoEntry const* displayScaleEntry = nullptr;
-
- if (cInfo->Modelid1)
- {
- CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid1);
- if (!displayEntry)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid1 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid1);
- const_cast<CreatureTemplate*>(cInfo)->Modelid1 = 0;
- }
- else
- displayScaleEntry = displayEntry;
-
- CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid1);
- if (!modelInfo)
- TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid1` = %u listed by creature (Entry: %u).", cInfo->Modelid1, cInfo->Entry);
- }
-
- if (cInfo->Modelid2)
- {
- CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid2);
- if (!displayEntry)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid2 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid2);
- const_cast<CreatureTemplate*>(cInfo)->Modelid2 = 0;
- }
- else if (!displayScaleEntry)
- displayScaleEntry = displayEntry;
-
- CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid2);
- if (!modelInfo)
- TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid2` = %u listed by creature (Entry: %u).", cInfo->Modelid2, cInfo->Entry);
- }
-
- if (cInfo->Modelid3)
- {
- CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid3);
- if (!displayEntry)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid3 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid3);
- const_cast<CreatureTemplate*>(cInfo)->Modelid3 = 0;
- }
- else if (!displayScaleEntry)
- displayScaleEntry = displayEntry;
-
- CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid3);
- if (!modelInfo)
- TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid3` = %u listed by creature (Entry: %u).", cInfo->Modelid3, cInfo->Entry);
- }
-
- if (cInfo->Modelid4)
- {
- CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid4);
- if (!displayEntry)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) lists non-existing Modelid4 id (%u), this can crash the client.", cInfo->Entry, cInfo->Modelid4);
- const_cast<CreatureTemplate*>(cInfo)->Modelid4 = 0;
- }
- else if (!displayScaleEntry)
- displayScaleEntry = displayEntry;
-
- CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid4);
- if (!modelInfo)
- TC_LOG_ERROR("sql.sql", "No model data exist for `Modelid4` = %u listed by creature (Entry: %u).", cInfo->Modelid4, cInfo->Entry);
- }
-
- if (!displayScaleEntry)
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo->Entry);
-
for (uint8 k = 0; k < MAX_KILL_CREDIT; ++k)
{
if (cInfo->KillCredit[k])
@@ -949,6 +932,11 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
}
}
+ if (!cInfo->Models.size())
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) does not have any existing display id in creature_template_model.", cInfo->Entry);
+ else if (std::accumulate(cInfo->Models.begin(), cInfo->Models.end(), 0.0f, [](float sum, CreatureModel const& model) { return sum + model.Probability; }) <= 0.0f)
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has zero total chance for all models in creature_template_model.", cInfo->Entry);
+
if (!cInfo->unit_class || ((1 << (cInfo->unit_class-1)) & CLASSMASK_ALL_CREATURES) == 0)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid unit_class (%u) in creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo->Entry, cInfo->unit_class);
@@ -1029,15 +1017,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
const_cast<CreatureTemplate*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
}
- /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
- if (cInfo->scale <= 0.0f)
- {
- if (displayScaleEntry)
- const_cast<CreatureTemplate*>(cInfo)->scale = displayScaleEntry->CreatureModelScale;
- else
- const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f;
- }
-
if (cInfo->HealthScalingExpansion < EXPANSION_LEVEL_CURRENT || cInfo->HealthScalingExpansion > (MAX_EXPANSIONS - 1))
{
TC_LOG_ERROR("sql.sql", "Table `creature_template` lists creature (ID: %u) with invalid `HealthScalingExpansion` %i. Ignored and set to 0.", cInfo->Entry, cInfo->HealthScalingExpansion);
@@ -1409,14 +1388,16 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelId) const
return nullptr;
}
-uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/)
+CreatureModel const* ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/)
{
// Load creature model (display id)
if (data && data->displayid)
- return data->displayid;
+ if (CreatureModel const* model = cinfo->GetModelWithDisplayId(data->displayid))
+ return model;
if (!(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER))
- return cinfo->GetRandomValidModelId();
+ if (CreatureModel const* model = cinfo->GetRandomValidModel())
+ return model;
// Triggers by default receive the invisible model
return cinfo->GetFirstInvisibleModel();
@@ -1449,9 +1430,9 @@ void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64& npcFl
}
}
-CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* displayID) const
+CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const
{
- CreatureModelInfo const* modelInfo = GetCreatureModelInfo(*displayID);
+ CreatureModelInfo const* modelInfo = GetCreatureModelInfo(model->CreatureDisplayID);
if (!modelInfo)
return nullptr;
@@ -1460,11 +1441,20 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* display
{
CreatureModelInfo const* minfo_tmp = GetCreatureModelInfo(modelInfo->displayId_other_gender);
if (!minfo_tmp)
- TC_LOG_ERROR("sql.sql", "Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. ", *displayID, modelInfo->displayId_other_gender);
+ TC_LOG_ERROR("sql.sql", "Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. ", model->CreatureDisplayID, modelInfo->displayId_other_gender);
else
{
// DisplayID changed
- *displayID = modelInfo->displayId_other_gender;
+ model->CreatureDisplayID = modelInfo->displayId_other_gender;
+ if (creatureTemplate)
+ {
+ auto itr = std::find_if(creatureTemplate->Models.begin(), creatureTemplate->Models.end(), [&](CreatureModel const& templateModel)
+ {
+ return templateModel.CreatureDisplayID == modelInfo->displayId_other_gender;
+ });
+ if (itr != creatureTemplate->Models.end())
+ *model = *itr;
+ }
return minfo_tmp;
}
}
@@ -6234,7 +6224,8 @@ void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uin
uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team /* = false */)
{
- uint32 mount_id = 0;
+ CreatureModel mountModel;
+ CreatureTemplate const* mount_info = nullptr;
// select mount creature id
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
@@ -6254,22 +6245,23 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt
mount_entry = team == ALLIANCE ? node->MountCreatureID[0] : node->MountCreatureID[1];
}
- CreatureTemplate const* mount_info = GetCreatureTemplate(mount_entry);
+ mount_info = GetCreatureTemplate(mount_entry);
if (mount_info)
{
- mount_id = mount_info->GetRandomValidModelId();
- if (!mount_id)
+ CreatureModel const* model = mount_info->GetRandomValidModel();
+ if (!model)
{
TC_LOG_ERROR("sql.sql", "No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry);
return 0;
}
+ mountModel = *model;
}
}
// minfo is not actually used but the mount_id was updated
- GetCreatureModelRandomGender(&mount_id);
+ GetCreatureModelRandomGender(&mountModel, mount_info);
- return mount_id;
+ return mountModel.CreatureDisplayID;
}
void ObjectMgr::LoadGraveyardZones()
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 01ce6ee385d..7052bc790ca 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -962,8 +962,8 @@ class TC_GAME_API ObjectMgr
CreatureTemplate const* GetCreatureTemplate(uint32 entry) const;
CreatureTemplateContainer const* GetCreatureTemplates() const { return &_creatureTemplateStore; }
CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId) const;
- CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID) const;
- static uint32 ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr);
+ CreatureModelInfo const* GetCreatureModelRandomGender(CreatureModel* mode, CreatureTemplate const* creatureTemplate) const;
+ static CreatureModel const* ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr);
static void ChooseCreatureFlags(CreatureTemplate const* cInfo, uint64& npcFlags, uint32& unitFlags, uint32& unitFlags2, uint32& unitFlags3, uint32& dynamicFlags, CreatureData const* data = nullptr);
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id) const;
CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid) const;
@@ -1185,6 +1185,7 @@ class TC_GAME_API ObjectMgr
void LoadCreatureClassLevelStats();
void LoadCreatureLocales();
void LoadCreatureTemplates();
+ void LoadCreatureTemplateModels();
void LoadCreatureTemplateAddons();
void LoadCreatureTemplate(Field* fields);
void LoadCreatureScalingData();
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index 0e0a9f4ac43..48bb45581fa 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -95,22 +95,12 @@ void WorldSession::HandleCreatureQuery(WorldPackets::Query::QueryCreature& packe
for (uint32 i = 0; i < MAX_KILL_CREDIT; ++i)
stats.ProxyCreatureID[i] = creatureInfo->KillCredit[i];
- // TEMPORARY, PR #22567
- auto addModel = [&](uint32 modelId)
+ std::transform(creatureInfo->Models.begin(), creatureInfo->Models.end(), std::back_inserter(stats.Display.CreatureDisplay),
+ [&stats](CreatureModel const& model) -> WorldPackets::Query::CreatureXDisplay
{
- if (modelId)
- {
- stats.Display.TotalProbability += 1.0f;
- stats.Display.CreatureDisplay.emplace_back();
- WorldPackets::Query::CreatureXDisplay& display = stats.Display.CreatureDisplay.back();
- display.CreatureDisplayID = modelId;
- }
- };
-
- addModel(creatureInfo->Modelid1);
- addModel(creatureInfo->Modelid2);
- addModel(creatureInfo->Modelid3);
- addModel(creatureInfo->Modelid4);
+ stats.Display.TotalProbability += model.Probability;
+ return { model.CreatureDisplayID, model.DisplayScale, model.Probability };
+ });
stats.HpMulti = creatureInfo->ModHealth;
stats.EnergyMulti = creatureInfo->ModMana;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index c663a16c270..a45c8a84ab4 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2011,7 +2011,7 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
uint32 model_id = 0;
// choose a model, based on trigger flag
- if (uint32 modelid = sObjectMgr->ChooseDisplayId(ci))
+ if (uint32 modelid = ObjectMgr::ChooseDisplayId(ci)->CreatureDisplayID)
model_id = modelid;
target->SetDisplayId(model_id);
@@ -2052,10 +2052,10 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue();
if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(cr_id))
{
- uint32 displayID = ObjectMgr::ChooseDisplayId(ci);
- sObjectMgr->GetCreatureModelRandomGender(&displayID);
+ CreatureModel model = *ObjectMgr::ChooseDisplayId(ci);
+ sObjectMgr->GetCreatureModelRandomGender(&model, ci);
- target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID);
+ target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID);
}
}
}
@@ -2553,8 +2553,9 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
if (!displayId)
{
- displayId = ObjectMgr::ChooseDisplayId(creatureInfo);
- sObjectMgr->GetCreatureModelRandomGender(&displayId);
+ CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo);
+ sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
+ displayId = model.CreatureDisplayID;
}
//some spell has one aura of mount and one of vehicle
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index a17824a0127..6dc2d9b84f2 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -493,7 +493,10 @@ public:
if (CheckModifySpeed(handler, args, target, Scale, 0.1f, 10.0f, false))
{
NotifyModification(handler, target, LANG_YOU_CHANGE_SIZE, LANG_YOURS_SIZE_CHANGED, Scale);
- target->SetObjectScale(Scale);
+ if (Creature* creatureTarget = target->ToCreature())
+ creatureTarget->SetFloatValue(UNIT_FIELD_DISPLAY_SCALE, Scale);
+ else
+ target->SetObjectScale(Scale);
return true;
}
return false;
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
index 8bd6650b1ad..e0963b46057 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
@@ -203,7 +203,7 @@ class npc_pure_energy : public CreatureScript
{
npc_pure_energyAI(Creature* creature) : ScriptedAI(creature)
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
}
void JustDied(Unit* killer) override
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index 9c1ff991279..c69a3287134 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -370,7 +370,7 @@ class npc_eye_of_acherus : public CreatureScript
{
npc_eye_of_acherusAI(Creature* creature) : ScriptedAI(creature)
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
+ me->SetDisplayFromModel(0);
if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
{
me->GetCharmInfo()->InitPossessCreateSpells();
@@ -1023,7 +1023,7 @@ class npc_scarlet_miner_cart : public CreatureScript
{
npc_scarlet_miner_cartAI(Creature* creature) : PassiveAI(creature)
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse.
+ me->SetDisplayFromModel(0); // Modelid2
}
void JustSummoned(Creature* summon) override
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp
index 33c745c63c2..e36fb0ac437 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp
@@ -402,7 +402,7 @@ public:
void Initialize()
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
me->SetReactState(REACT_PASSIVE);
DoCast(me, SPELL_DARKFIEND_SKIN, true);
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
index fca2d98002a..4822c5138e5 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
@@ -91,7 +91,7 @@ class npc_voljin_zulaman : public CreatureScript
{
npc_voljin_zulamanAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
+ me->SetDisplayFromModel(0);
if (_instance->GetData(DATA_ZULAMAN_STATE) == NOT_STARTED)
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
diff --git a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
index d437ec8dba9..82282ed3613 100644
--- a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
@@ -324,7 +324,6 @@ public:
{
_events.Reset();
_events.ScheduleEvent(EVENT_DETERMINE_EVENT, Seconds(2));
- me->SetDisplayId(me->GetCreatureTemplate()->GetRandomValidModelId());
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
index 705c82b799b..8e5dc67299e 100644
--- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
+++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
@@ -248,7 +248,7 @@ public:
void Reset() override
{
_events.Reset();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
}
void EnterCombat(Unit* /*who*/) override
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp
index 934143da40e..69f6d3ce2c1 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp
@@ -173,7 +173,7 @@ public:
events.Reset();
events.ScheduleEvent(EVENT_AURA, 1 * IN_MILLISECONDS);
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
DoCast(SPELL_PUTRID_MUSHROOM);
if (me->GetEntry() == NPC_POISONOUS_MUSHROOM)
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
index ce900cef73c..2be65088628 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -254,10 +254,10 @@ class boss_anubarak_trial : public CreatureScript
_burrowGUID.push_back(summoned->GetGUID());
summoned->SetReactState(REACT_PASSIVE);
summoned->CastSpell(summoned, SPELL_CHURNING_GROUND, false);
- summoned->SetDisplayId(summoned->GetCreatureTemplate()->Modelid2);
+ summoned->SetDisplayFromModel(1);
break;
case NPC_SPIKE:
- summoned->SetDisplayId(summoned->GetCreatureTemplate()->Modelid1);
+ summoned->SetDisplayFromModel(0);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
summoned->CombatStart(target);
@@ -620,7 +620,7 @@ class npc_frost_sphere : public CreatureScript
{
me->SetReactState(REACT_PASSIVE);
DoCast(SPELL_FROST_SPHERE);
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
me->GetMotionMaster()->MoveRandom(20.0f);
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index 8cb3f23d346..165e15c61c4 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -489,7 +489,7 @@ class npc_firebomb : public CreatureScript
DoCast(me, SPELL_FIRE_BOMB_DOT, true);
SetCombatMovement(false);
me->SetReactState(REACT_PASSIVE);
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
}
void UpdateAI(uint32 /*diff*/) override
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
index b147ce86fcc..9dde78ac1e2 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
@@ -306,7 +306,7 @@ class boss_lich_king_toc : public CreatureScript
if (Creature* summoned = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[2].GetPositionX(), ToCCommonLoc[2].GetPositionY(), ToCCommonLoc[2].GetPositionZ(), 5, TEMPSUMMON_TIMED_DESPAWN, 1*MINUTE*IN_MILLISECONDS))
{
summoned->CastSpell(summoned, 51807, false);
- summoned->SetDisplayId(summoned->GetCreatureTemplate()->Modelid2);
+ summoned->SetDisplayFromModel(1);
}
_instance->SetBossState(BOSS_LICH_KING, IN_PROGRESS);
@@ -497,11 +497,11 @@ class npc_fizzlebang_toc : public CreatureScript
me->GetMotionMaster()->MovementExpired();
Talk(SAY_STAGE_1_03);
me->HandleEmoteCommand(EMOTE_ONESHOT_SPELL_CAST_OMNI);
- if (Unit* pTrigger = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.69494f, TEMPSUMMON_MANUAL_DESPAWN))
+ if (Creature* pTrigger = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.69494f, TEMPSUMMON_MANUAL_DESPAWN))
{
_triggerGUID = pTrigger->GetGUID();
pTrigger->SetObjectScale(2.0f);
- pTrigger->SetDisplayId(pTrigger->ToCreature()->GetCreatureTemplate()->Modelid1);
+ pTrigger->SetDisplayFromModel(0);
pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false);
}
_instance->SetData(TYPE_EVENT, 1132);
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index ab78e9a3cea..612d4b9316f 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -2587,7 +2587,7 @@ class npc_quel_delar_sword : public CreatureScript
npc_quel_delar_swordAI(Creature* creature) : ScriptedAI(creature)
{
_instance = me->GetInstanceScript();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
_intro = true;
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
index 1290d417189..a73a3a2fa0d 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp
@@ -272,7 +272,7 @@ class npc_pit_of_saron_icicle : public CreatureScript
{
npc_pit_of_saron_icicleAI(Creature* creature) : PassiveAI(creature)
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
+ me->SetDisplayFromModel(0);
}
void IsSummonedBy(Unit* summoner) override
diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp
index c4982c126f0..99513317306 100644
--- a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp
+++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp
@@ -224,7 +224,7 @@ class npc_chaotic_rift : public CreatureScript
void Reset() override
{
Initialize();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
DoCast(me, SPELL_ARCANEFORM, false);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
index 93f1f515409..7ca0d014c8a 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -586,7 +586,7 @@ class boss_flame_leviathan_seat : public CreatureScript
boss_flame_leviathan_seatAI(Creature* creature) : ScriptedAI(creature)
{
me->SetReactState(REACT_PASSIVE);
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
instance = creature->GetInstanceScript();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
index 5a85d720eea..fbcca717df6 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp
@@ -188,7 +188,7 @@ class npc_flash_freeze : public CreatureScript
{
Initialize();
instance = me->GetInstanceScript();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
me->SetControlled(true, UNIT_STATE_ROOT);
}
@@ -264,7 +264,7 @@ class npc_ice_block : public CreatureScript
npc_ice_blockAI(Creature* creature) : ScriptedAI(creature)
{
instance = me->GetInstanceScript();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
me->SetControlled(true, UNIT_STATE_ROOT);
}
@@ -557,7 +557,7 @@ class npc_icicle : public CreatureScript
npc_icicleAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
+ me->SetDisplayFromModel(0);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE);
me->SetControlled(true, UNIT_STATE_ROOT);
me->SetReactState(REACT_PASSIVE);
@@ -612,7 +612,7 @@ class npc_snowpacked_icicle : public CreatureScript
npc_snowpacked_icicleAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED);
me->SetControlled(true, UNIT_STATE_ROOT);
me->SetReactState(REACT_PASSIVE);
@@ -954,7 +954,7 @@ class npc_toasty_fire : public CreatureScript
{
npc_toasty_fireAI(Creature* creature) : ScriptedAI(creature)
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
}
void Reset() override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
index cc1c3219bca..4a1a41bcbf6 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -193,7 +193,7 @@ class boss_razorscale_controller : public CreatureScript
{
boss_razorscale_controllerAI(Creature* creature) : BossAI(creature, DATA_RAZORSCALE_CONTROL)
{
- me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ me->SetDisplayFromModel(1);
}
void Reset() override
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index 8b8e47245e0..e0c648bcfc4 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -2606,8 +2606,8 @@ public:
init.SetFacing(o);
init.Launch();
who->m_Events.AddEvent(new CastFoodSpell(who, _chairSpells.at(who->GetEntry())), who->m_Events.CalculateTime(1000));
- if (who->GetTypeId() == TYPEID_UNIT)
- who->SetDisplayId(who->ToCreature()->GetCreatureTemplate()->Modelid1);
+ if (Creature* creature = who->ToCreature())
+ creature->SetDisplayFromModel(0);
}
};