aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
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 /src/server/game/Entities
parent31f0186d20a1944e5d0ff47d71ca8f560074de4b (diff)
Core/Creatures: Update creature model handling with new display scale (#22567)
Diffstat (limited to 'src/server/game/Entities')
-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
7 files changed, 111 insertions, 86 deletions
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;}