aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp14
-rw-r--r--src/server/game/Entities/Creature/Creature.h9
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFields.cpp4
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFields.h1
-rw-r--r--src/server/game/Entities/Object/Updates/ViewerDependentValues.h30
5 files changed, 53 insertions, 5 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 16c61e12fec..fcc4980b669 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -671,6 +671,9 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
if (IsTrigger())
SetUninteractible(true);
+ if (HasNpcFlag(UNIT_NPC_FLAG_SPELLCLICK))
+ InitializeInteractSpellId();
+
InitializeReactState();
if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_TAUNT)
@@ -3688,3 +3691,14 @@ void Creature::SummonGraveyardTeleporter()
// ID - 46894 Summon Horde Graveyard Teleporter (SERVERSIDE)
SummonCreature(npcEntry, GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 1s, 0, 0);
}
+
+void Creature::InitializeInteractSpellId()
+{
+ auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(GetEntry());
+ auto itr = clickBounds.begin();
+ // Set InteractSpellID if there is only one row in npc_spellclick_spells in db for this creature
+ if (itr != clickBounds.end() && ++itr == clickBounds.end())
+ SetInteractSpellId(clickBounds.begin()->second.spellId);
+ else
+ SetInteractSpellId(0);
+}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 591a1750818..ff408fbd314 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -263,7 +263,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void AllLootRemovedFromCorpse();
uint16 GetLootMode() const { return m_LootMode; }
- bool HasLootMode(uint16 lootMode) { return (m_LootMode & lootMode) != 0; }
+ bool HasLootMode(uint16 lootMode) const { return (m_LootMode & lootMode) != 0; }
void SetLootMode(uint16 lootMode) { m_LootMode = lootMode; }
void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; }
void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; }
@@ -367,7 +367,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
// There's many places not ready for dynamic spawns. This allows them to live on for now.
void SetRespawnCompatibilityMode(bool mode = true) { m_respawnCompatibilityMode = mode; }
- bool GetRespawnCompatibilityMode() { return m_respawnCompatibilityMode; }
+ bool GetRespawnCompatibilityMode() const { return m_respawnCompatibilityMode; }
static float GetDamageMod(CreatureClassifications classification);
@@ -401,7 +401,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void AtDisengage() override;
void OverrideSparringHealthPct(std::vector<float> const& healthPct);
- float GetSparringHealthPct() { return _sparringHealthPct; }
+ float GetSparringHealthPct() const { return _sparringHealthPct; }
uint32 CalculateDamageForSparring(Unit* attacker, uint32 damage);
bool ShouldFakeDamageFrom(Unit* attacker);
@@ -432,6 +432,9 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
void SummonGraveyardTeleporter();
+ void InitializeInteractSpellId();
+ void SetInteractSpellId(int32 interactSpellId) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::InteractSpellID), interactSpellId); }
+
protected:
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.cpp b/src/server/game/Entities/Object/Updates/UpdateFields.cpp
index 905cc26e982..2e012897754 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFields.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateFields.cpp
@@ -1105,7 +1105,7 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi
data << int32(WildBattlePetLevel);
data << int32(BattlePetCompanionExperience);
data << uint32(BattlePetCompanionNameTimestamp);
- data << int32(InteractSpellID);
+ data << int32(ViewerDependentValue<InteractSpellIDTag>::GetValue(this, owner, receiver));
data << int32(ScaleDuration);
data << int32(LooksLikeMountID);
data << int32(LooksLikeCreatureID);
@@ -1670,7 +1670,7 @@ void UnitData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ignor
}
if (changesMask[114])
{
- data << int32(InteractSpellID);
+ data << int32(ViewerDependentValue<InteractSpellIDTag>::GetValue(this, owner, receiver));
}
if (changesMask[115])
{
diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h
index 626ba71ec11..078f0e5738c 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFields.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFields.h
@@ -376,6 +376,7 @@ struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<217>
UpdateField<int32, 96, 112> BattlePetCompanionExperience;
UpdateField<uint32, 96, 113> BattlePetCompanionNameTimestamp;
UpdateField<int32, 96, 114> InteractSpellID;
+ struct InteractSpellIDTag : ViewerDependentValueTag<int32> {};
UpdateField<int32, 96, 115> ScaleDuration;
UpdateField<int32, 96, 116> LooksLikeMountID;
UpdateField<int32, 96, 117> LooksLikeCreatureID;
diff --git a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
index 371c0e2ab39..852ba9b86e3 100644
--- a/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
+++ b/src/server/game/Entities/Object/Updates/ViewerDependentValues.h
@@ -288,6 +288,36 @@ public:
};
template<>
+class ViewerDependentValue<UF::UnitData::InteractSpellIDTag>
+{
+public:
+ using value_type = UF::UnitData::InteractSpellIDTag::value_type;
+
+ static value_type GetValue(UF::UnitData const* unitData, Unit const* unit, Player const* receiver)
+ {
+ value_type interactSpellId = unitData->InteractSpellID;
+ if (unitData->NpcFlags[0] & UNIT_NPC_FLAG_SPELLCLICK && !interactSpellId)
+ {
+ // this field is not set if there are multiple available spellclick spells
+ auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(unit->GetEntry());
+ for (auto const& [creatureId, spellClickInfo] : clickBounds)
+ {
+ if (!spellClickInfo.IsFitToRequirements(receiver, unit))
+ continue;
+
+ if (!sConditionMgr->IsObjectMeetingSpellClickConditions(unit->GetEntry(), spellClickInfo.spellId, receiver, unit))
+ continue;
+
+ interactSpellId = spellClickInfo.spellId;
+ break;
+ }
+
+ }
+ return interactSpellId;
+ }
+};
+
+template<>
class ViewerDependentValue<UF::UnitData::NpcFlagsTag>
{
public: