diff options
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: |