Core/Creatures: Set InteractSpellID for npc spellclick
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user