Core/Creatures: Set InteractSpellID for npc spellclick

This commit is contained in:
Shauren
2024-02-10 14:20:09 +01:00
parent 761dac8f4a
commit 6543d23a1a
5 changed files with 53 additions and 5 deletions
@@ -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);
}
+6 -3
View File
@@ -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);
@@ -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])
{
@@ -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;
@@ -287,6 +287,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>
{