feat(Core/Optimization): Optimize build of units update object by leveraging cache (#18637)
* feat(Core/Optimization): Optimize build of units update object by leveraging cache. * Remove whitespaces. * Add alternative hooks to handle transmog and other similar things. * Fix build on some compilers. * Fix codestyle * Fix build again. * Take into account updateType.
This commit is contained in:
committed by
GitHub
parent
94df67b1c2
commit
1f640c9872
@@ -198,7 +198,7 @@ void Corpse::ResetGhostTime()
|
|||||||
m_time = GameTime::GetGameTime().count();
|
m_time = GameTime::GetGameTime().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Corpse::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
|
void Corpse::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
void AddToWorld() override;
|
void AddToWorld() override;
|
||||||
void RemoveFromWorld() override;
|
void RemoveFromWorld() override;
|
||||||
|
|
||||||
void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const override;
|
void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) override;
|
||||||
|
|
||||||
bool Create(ObjectGuid::LowType guidlow);
|
bool Create(ObjectGuid::LowType guidlow);
|
||||||
bool Create(ObjectGuid::LowType guidlow, Player* owner);
|
bool Create(ObjectGuid::LowType guidlow, Player* owner);
|
||||||
|
|||||||
@@ -2738,7 +2738,7 @@ GameObject* GameObject::GetLinkedTrap()
|
|||||||
return ObjectAccessor::GetGameObject(*this, m_linkedTrap);
|
return ObjectAccessor::GetGameObject(*this, m_linkedTrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
|
void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public:
|
|||||||
explicit GameObject();
|
explicit GameObject();
|
||||||
~GameObject() override;
|
~GameObject() override;
|
||||||
|
|
||||||
void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const override;
|
void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) override;
|
||||||
|
|
||||||
void AddToWorld() override;
|
void AddToWorld() override;
|
||||||
void RemoveFromWorld() override;
|
void RemoveFromWorld() override;
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ void Bag::StoreItem(uint8 slot, Item* pItem, bool /*update*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bag::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
|
void Bag::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target)
|
||||||
{
|
{
|
||||||
Item::BuildCreateUpdateBlockForPlayer(data, target);
|
Item::BuildCreateUpdateBlockForPlayer(data, target);
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
// overwrite virtual Item::DeleteFromDB
|
// overwrite virtual Item::DeleteFromDB
|
||||||
void DeleteFromDB(CharacterDatabaseTransaction trans) override;
|
void DeleteFromDB(CharacterDatabaseTransaction trans) override;
|
||||||
|
|
||||||
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override;
|
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) override;
|
||||||
|
|
||||||
std::string GetDebugInfo() const override;
|
std::string GetDebugInfo() const override;
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const
|
|||||||
data->AddUpdateBlock(buf);
|
data->AddUpdateBlock(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
|
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
@@ -254,7 +254,7 @@ void Object::SendUpdateToPlayer(Player* player)
|
|||||||
player->GetSession()->SendPacket(&packet);
|
player->GetSession()->SendPacket(&packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) const
|
void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target)
|
||||||
{
|
{
|
||||||
ByteBuffer buf(500);
|
ByteBuffer buf(500);
|
||||||
|
|
||||||
@@ -494,7 +494,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
|
void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
@@ -542,7 +542,7 @@ void Object::ClearUpdateMask(bool remove)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) const
|
void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map)
|
||||||
{
|
{
|
||||||
UpdateDataMapType::iterator iter = data_map.find(player);
|
UpdateDataMapType::iterator iter = data_map.find(player);
|
||||||
|
|
||||||
|
|||||||
@@ -121,10 +121,10 @@ public:
|
|||||||
[[nodiscard]] TypeID GetTypeId() const { return m_objectTypeId; }
|
[[nodiscard]] TypeID GetTypeId() const { return m_objectTypeId; }
|
||||||
[[nodiscard]] bool isType(uint16 mask) const { return (mask & m_objectType); }
|
[[nodiscard]] bool isType(uint16 mask) const { return (mask & m_objectType); }
|
||||||
|
|
||||||
virtual void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const;
|
virtual void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target);
|
||||||
void SendUpdateToPlayer(Player* player);
|
void SendUpdateToPlayer(Player* player);
|
||||||
|
|
||||||
void BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) const;
|
void BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target);
|
||||||
void BuildOutOfRangeUpdateBlock(UpdateData* data) const;
|
void BuildOutOfRangeUpdateBlock(UpdateData* data) const;
|
||||||
void BuildMovementUpdateBlock(UpdateData* data, uint32 flags = 0) const;
|
void BuildMovementUpdateBlock(UpdateData* data, uint32 flags = 0) const;
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ public:
|
|||||||
[[nodiscard]] virtual bool hasQuest(uint32 /* quest_id */) const { return false; }
|
[[nodiscard]] virtual bool hasQuest(uint32 /* quest_id */) const { return false; }
|
||||||
[[nodiscard]] virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; }
|
[[nodiscard]] virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; }
|
||||||
virtual void BuildUpdate(UpdateDataMapType&, UpdatePlayerSet&) {}
|
virtual void BuildUpdate(UpdateDataMapType&, UpdatePlayerSet&) {}
|
||||||
void BuildFieldsUpdate(Player*, UpdateDataMapType&) const;
|
void BuildFieldsUpdate(Player*, UpdateDataMapType&);
|
||||||
|
|
||||||
void SetFieldNotifyFlag(uint16 flag) { _fieldNotifyFlags |= flag; }
|
void SetFieldNotifyFlag(uint16 flag) { _fieldNotifyFlags |= flag; }
|
||||||
void RemoveFieldNotifyFlag(uint16 flag) { _fieldNotifyFlags &= ~flag; }
|
void RemoveFieldNotifyFlag(uint16 flag) { _fieldNotifyFlags &= ~flag; }
|
||||||
@@ -223,7 +223,7 @@ protected:
|
|||||||
uint32 GetUpdateFieldData(Player const* target, uint32*& flags) const;
|
uint32 GetUpdateFieldData(Player const* target, uint32*& flags) const;
|
||||||
|
|
||||||
void BuildMovementUpdate(ByteBuffer* data, uint16 flags) const;
|
void BuildMovementUpdate(ByteBuffer* data, uint16 flags) const;
|
||||||
virtual void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const;
|
virtual void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target);
|
||||||
|
|
||||||
uint16 m_objectType;
|
uint16 m_objectType;
|
||||||
|
|
||||||
|
|||||||
@@ -3791,7 +3791,7 @@ Mail* Player::GetMail(uint32 id)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
|
void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target)
|
||||||
{
|
{
|
||||||
if (target == this)
|
if (target == this)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1974,7 +1974,7 @@ public:
|
|||||||
[[nodiscard]] WorldSession* GetSession() const { return m_session; }
|
[[nodiscard]] WorldSession* GetSession() const { return m_session; }
|
||||||
void SetSession(WorldSession* sess) { m_session = sess; }
|
void SetSession(WorldSession* sess) { m_session = sess; }
|
||||||
|
|
||||||
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override;
|
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) override;
|
||||||
void DestroyForPlayer(Player* target, bool onDeath = false) const override;
|
void DestroyForPlayer(Player* target, bool onDeath = false) const override;
|
||||||
void SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 BonusXP, bool recruitAFriend = false, float group_rate = 1.0f);
|
void SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 BonusXP, bool recruitAFriend = false, float group_rate = 1.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -534,6 +534,8 @@ void Unit::Update(uint32 p_time)
|
|||||||
|
|
||||||
UpdateSplineMovement(p_time);
|
UpdateSplineMovement(p_time);
|
||||||
GetMotionMaster()->UpdateMotion(p_time);
|
GetMotionMaster()->UpdateMotion(p_time);
|
||||||
|
|
||||||
|
InvalidateValuesUpdateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Unit::haveOffhandWeapon() const
|
bool Unit::haveOffhandWeapon() const
|
||||||
@@ -21034,16 +21036,11 @@ void Unit::SendMovementHover(Player* sendTo)
|
|||||||
sendTo->SendDirectMessage(&data);
|
sendTo->SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
|
void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
||||||
{
|
{
|
||||||
if (!target)
|
if (!target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ByteBuffer fieldBuffer;
|
|
||||||
|
|
||||||
UpdateMask updateMask;
|
|
||||||
updateMask.SetCount(m_valuesCount);
|
|
||||||
|
|
||||||
uint32* flags = UnitUpdateFieldFlags;
|
uint32* flags = UnitUpdateFieldFlags;
|
||||||
uint32 visibleFlag = UF_FLAG_PUBLIC;
|
uint32 visibleFlag = UF_FLAG_PUBLIC;
|
||||||
|
|
||||||
@@ -21061,7 +21058,30 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
|||||||
if (plr && plr->IsInSameRaidWith(target))
|
if (plr && plr->IsInSameRaidWith(target))
|
||||||
visibleFlag |= UF_FLAG_PARTY_MEMBER;
|
visibleFlag |= UF_FLAG_PARTY_MEMBER;
|
||||||
|
|
||||||
Creature const* creature = ToCreature();
|
uint64 cacheKey = static_cast<uint64>(visibleFlag) << 8 | updateType;
|
||||||
|
|
||||||
|
auto cacheIt = _valuesUpdateCache.find(cacheKey);
|
||||||
|
if (cacheIt != _valuesUpdateCache.end())
|
||||||
|
{
|
||||||
|
int32 cachePos = static_cast<int32>(data->wpos());
|
||||||
|
data->append(cacheIt->second.buffer);
|
||||||
|
|
||||||
|
BuildValuesCachePosPointers dataAdjustedPos = cacheIt->second.posPointers;
|
||||||
|
if (cachePos)
|
||||||
|
dataAdjustedPos.ApplyOffset(cachePos);
|
||||||
|
|
||||||
|
PatchValuesUpdate(*data, dataAdjustedPos, target);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildValuesCachedBuffer cacheValue(500);
|
||||||
|
|
||||||
|
ByteBuffer fieldBuffer(400);
|
||||||
|
|
||||||
|
UpdateMask updateMask;
|
||||||
|
updateMask.SetCount(m_valuesCount);
|
||||||
|
|
||||||
for (uint16 index = 0; index < m_valuesCount; ++index)
|
for (uint16 index = 0; index < m_valuesCount; ++index)
|
||||||
{
|
{
|
||||||
if (_fieldNotifyFlags & flags[index] ||
|
if (_fieldNotifyFlags & flags[index] ||
|
||||||
@@ -21073,37 +21093,13 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
|||||||
|
|
||||||
if (index == UNIT_NPC_FLAGS)
|
if (index == UNIT_NPC_FLAGS)
|
||||||
{
|
{
|
||||||
uint32 appendValue = m_uint32Values[UNIT_NPC_FLAGS];
|
cacheValue.posPointers.UnitNPCFlagsPos = int32(fieldBuffer.wpos());
|
||||||
|
fieldBuffer << m_uint32Values[UNIT_NPC_FLAGS];
|
||||||
if (creature)
|
|
||||||
{
|
|
||||||
if (sWorld->getIntConfig(CONFIG_INSTANT_TAXI) == 2 && appendValue & UNIT_NPC_FLAG_FLIGHTMASTER)
|
|
||||||
{
|
|
||||||
appendValue |= UNIT_NPC_FLAG_GOSSIP; // flight masters need NPC gossip flag to show instant flight toggle option
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target->CanSeeSpellClickOn(creature))
|
|
||||||
{
|
|
||||||
appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target->CanSeeVendor(creature))
|
|
||||||
{
|
|
||||||
appendValue &= ~UNIT_NPC_FLAG_VENDOR_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!creature->IsValidTrainerForPlayer(target, &appendValue))
|
|
||||||
{
|
|
||||||
appendValue &= ~UNIT_NPC_FLAG_TRAINER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldBuffer << uint32(appendValue);
|
|
||||||
}
|
}
|
||||||
else if (index == UNIT_FIELD_AURASTATE)
|
else if (index == UNIT_FIELD_AURASTATE)
|
||||||
{
|
{
|
||||||
// Check per caster aura states to not enable using a spell in client if specified aura is not by target
|
cacheValue.posPointers.UnitFieldAuraStatePos = int32(fieldBuffer.wpos());
|
||||||
fieldBuffer << BuildAuraStateUpdateForTarget(target);
|
fieldBuffer << uint32(0); // Fill in later.
|
||||||
}
|
}
|
||||||
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
|
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
|
||||||
else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
|
else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
|
||||||
@@ -21122,115 +21118,35 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
|||||||
// Gamemasters should be always able to select units - remove not selectable flag
|
// Gamemasters should be always able to select units - remove not selectable flag
|
||||||
else if (index == UNIT_FIELD_FLAGS)
|
else if (index == UNIT_FIELD_FLAGS)
|
||||||
{
|
{
|
||||||
uint32 appendValue = m_uint32Values[UNIT_FIELD_FLAGS];
|
cacheValue.posPointers.UnitFieldFlagsPos = int32(fieldBuffer.wpos());
|
||||||
if (target->IsGameMaster() && target->GetSession()->IsGMAccount())
|
fieldBuffer << m_uint32Values[UNIT_FIELD_FLAGS];
|
||||||
appendValue &= ~UNIT_FLAG_NOT_SELECTABLE;
|
|
||||||
|
|
||||||
fieldBuffer << uint32(appendValue);
|
|
||||||
}
|
}
|
||||||
// use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
|
// use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
|
||||||
else if (index == UNIT_FIELD_DISPLAYID)
|
else if (index == UNIT_FIELD_DISPLAYID)
|
||||||
{
|
{
|
||||||
uint32 displayId = m_uint32Values[UNIT_FIELD_DISPLAYID];
|
cacheValue.posPointers.UnitFieldDisplayPos = int32(fieldBuffer.wpos());
|
||||||
if (creature)
|
fieldBuffer << m_uint32Values[UNIT_FIELD_DISPLAYID];
|
||||||
{
|
|
||||||
CreatureTemplate const* cinfo = creature->GetCreatureTemplate();
|
|
||||||
|
|
||||||
// this also applies for transform auras
|
|
||||||
if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm()))
|
|
||||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
|
||||||
if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM))
|
|
||||||
if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue))
|
|
||||||
{
|
|
||||||
cinfo = transformInfo;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
|
|
||||||
{
|
|
||||||
if (target->IsGameMaster() && target->GetSession()->IsGMAccount())
|
|
||||||
{
|
|
||||||
if (cinfo->Modelid1)
|
|
||||||
displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms
|
|
||||||
else
|
|
||||||
displayId = 17519; // world visible trigger's model
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cinfo->Modelid2)
|
|
||||||
displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players
|
|
||||||
else
|
|
||||||
displayId = 11686; // world invisible trigger's model
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldBuffer << uint32(displayId);
|
|
||||||
}
|
}
|
||||||
// hide lootable animation for unallowed players
|
|
||||||
else if (index == UNIT_DYNAMIC_FLAGS)
|
else if (index == UNIT_DYNAMIC_FLAGS)
|
||||||
{
|
{
|
||||||
|
cacheValue.posPointers.UnitDynamicFlagsPos = int32(fieldBuffer.wpos());
|
||||||
uint32 dynamicFlags = m_uint32Values[UNIT_DYNAMIC_FLAGS] & ~(UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER);
|
uint32 dynamicFlags = m_uint32Values[UNIT_DYNAMIC_FLAGS] & ~(UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER);
|
||||||
|
|
||||||
if (creature)
|
|
||||||
{
|
|
||||||
if (creature->hasLootRecipient())
|
|
||||||
{
|
|
||||||
dynamicFlags |= UNIT_DYNFLAG_TAPPED;
|
|
||||||
if (creature->isTappedBy(target))
|
|
||||||
dynamicFlags |= UNIT_DYNFLAG_TAPPED_BY_PLAYER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target->isAllowedToLoot(creature))
|
|
||||||
dynamicFlags &= ~UNIT_DYNFLAG_LOOTABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
|
|
||||||
if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
|
|
||||||
if (!HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID()))
|
|
||||||
dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
|
|
||||||
|
|
||||||
fieldBuffer << dynamicFlags;
|
fieldBuffer << dynamicFlags;
|
||||||
}
|
}
|
||||||
// FG: pretend that OTHER players in own group are friendly ("blue")
|
else if (index == UNIT_FIELD_BYTES_2)
|
||||||
else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE)
|
|
||||||
{
|
{
|
||||||
if (IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsInRaidWith(target))
|
cacheValue.posPointers.UnitFieldBytes2Pos = int32(fieldBuffer.wpos());
|
||||||
{
|
fieldBuffer << m_uint32Values[index];
|
||||||
FactionTemplateEntry const* ft1 = GetFactionTemplateEntry();
|
}
|
||||||
FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry();
|
else if (index == UNIT_FIELD_FACTIONTEMPLATE)
|
||||||
if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
|
{
|
||||||
{
|
cacheValue.posPointers.UnitFieldFactionTemplatePos = int32(fieldBuffer.wpos());
|
||||||
if (index == UNIT_FIELD_BYTES_2)
|
fieldBuffer << m_uint32Values[index];
|
||||||
// Allow targetting opposite faction in party when enabled in config
|
|
||||||
fieldBuffer << (m_uint32Values[UNIT_FIELD_BYTES_2] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8)); // this flag is at uint8 offset 1 !!
|
|
||||||
else
|
|
||||||
// pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
|
|
||||||
fieldBuffer << uint32(target->GetFaction());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fieldBuffer << m_uint32Values[index];
|
|
||||||
}// pussywizard / Callmephil
|
|
||||||
else if (target->IsSpectator() && target->FindMap() && target->FindMap()->IsBattleArena() &&
|
|
||||||
(this->GetTypeId() == TYPEID_PLAYER || this->GetTypeId() == TYPEID_UNIT || this->GetTypeId() == TYPEID_DYNAMICOBJECT))
|
|
||||||
{
|
|
||||||
if (index == UNIT_FIELD_BYTES_2)
|
|
||||||
fieldBuffer << (m_uint32Values[index] & 0xFFFFF2FF); // clear UNIT_BYTE2_FLAG_PVP, UNIT_BYTE2_FLAG_FFA_PVP, UNIT_BYTE2_FLAG_SANCTUARY
|
|
||||||
else
|
|
||||||
fieldBuffer << (uint32)target->GetFaction();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (!sScriptMgr->IsCustomBuildValuesUpdate(this, updateType, fieldBuffer, target, index))
|
|
||||||
{
|
|
||||||
fieldBuffer << m_uint32Values[index];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sScriptMgr->OnBuildValuesUpdate(this, updateType, fieldBuffer, target, index))
|
if (sScriptMgr->ShouldTrackValuesUpdatePosByIndex(this, updateType, index))
|
||||||
{
|
cacheValue.posPointers.other[index] = static_cast<uint32>(fieldBuffer.wpos());
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send in current format (float as float, uint32 as uint32)
|
// send in current format (float as float, uint32 as uint32)
|
||||||
fieldBuffer << m_uint32Values[index];
|
fieldBuffer << m_uint32Values[index];
|
||||||
@@ -21238,9 +21154,167 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*data << uint8(updateMask.GetBlockCount());
|
cacheValue.buffer << uint8(updateMask.GetBlockCount());
|
||||||
updateMask.AppendToPacket(data);
|
updateMask.AppendToPacket(&cacheValue.buffer);
|
||||||
data->append(fieldBuffer);
|
int32 fieldBufferPos = static_cast<int32>(cacheValue.buffer.wpos());
|
||||||
|
cacheValue.buffer.append(fieldBuffer);
|
||||||
|
cacheValue.posPointers.ApplyOffset(fieldBufferPos);
|
||||||
|
|
||||||
|
int32 cachePos = static_cast<int32>(data->wpos());
|
||||||
|
data->append(cacheValue.buffer);
|
||||||
|
|
||||||
|
BuildValuesCachePosPointers dataAdjustedPos = cacheValue.posPointers;
|
||||||
|
if (cachePos)
|
||||||
|
dataAdjustedPos.ApplyOffset(cachePos);
|
||||||
|
|
||||||
|
PatchValuesUpdate(*data, dataAdjustedPos, target);
|
||||||
|
|
||||||
|
_valuesUpdateCache.insert(std::pair<uint64, BuildValuesCachedBuffer>(cacheKey, std::move(cacheValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unit::PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPointers& posPointers, Player* target)
|
||||||
|
{
|
||||||
|
Creature const* creature = ToCreature();
|
||||||
|
|
||||||
|
// UNIT_NPC_FLAGS
|
||||||
|
if (creature && posPointers.UnitNPCFlagsPos >= 0)
|
||||||
|
{
|
||||||
|
uint32 appendValue = m_uint32Values[UNIT_NPC_FLAGS];
|
||||||
|
|
||||||
|
if (sWorld->getIntConfig(CONFIG_INSTANT_TAXI) == 2 && appendValue & UNIT_NPC_FLAG_FLIGHTMASTER)
|
||||||
|
appendValue |= UNIT_NPC_FLAG_GOSSIP; // flight masters need NPC gossip flag to show instant flight toggle option
|
||||||
|
|
||||||
|
if (!target->CanSeeSpellClickOn(creature))
|
||||||
|
appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
|
||||||
|
|
||||||
|
if (!target->CanSeeVendor(creature))
|
||||||
|
appendValue &= ~UNIT_NPC_FLAG_VENDOR_MASK;
|
||||||
|
|
||||||
|
if (!creature->IsValidTrainerForPlayer(target, &appendValue))
|
||||||
|
appendValue &= ~UNIT_NPC_FLAG_TRAINER;
|
||||||
|
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitNPCFlagsPos, appendValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNIT_FIELD_AURASTATE
|
||||||
|
if (posPointers.UnitFieldAuraStatePos >= 0)
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldAuraStatePos, uint32(BuildAuraStateUpdateForTarget(target)));
|
||||||
|
|
||||||
|
// UNIT_FIELD_FLAGS
|
||||||
|
if (posPointers.UnitFieldFlagsPos >= 0)
|
||||||
|
{
|
||||||
|
uint32 appendValue = m_uint32Values[UNIT_FIELD_FLAGS];
|
||||||
|
if (target->IsGameMaster() && target->GetSession()->IsGMAccount())
|
||||||
|
appendValue &= ~UNIT_FLAG_NOT_SELECTABLE;
|
||||||
|
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldFlagsPos, appendValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNIT_FIELD_DISPLAYID
|
||||||
|
// Use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures.
|
||||||
|
if (posPointers.UnitFieldDisplayPos >= 0)
|
||||||
|
{
|
||||||
|
uint32 displayId = m_uint32Values[UNIT_FIELD_DISPLAYID];
|
||||||
|
if (creature)
|
||||||
|
{
|
||||||
|
CreatureTemplate const* cinfo = creature->GetCreatureTemplate();
|
||||||
|
|
||||||
|
// this also applies for transform auras
|
||||||
|
if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm()))
|
||||||
|
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
|
if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM))
|
||||||
|
if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue))
|
||||||
|
{
|
||||||
|
cinfo = transformInfo;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
|
||||||
|
{
|
||||||
|
if (target->IsGameMaster() && target->GetSession()->IsGMAccount())
|
||||||
|
{
|
||||||
|
if (cinfo->Modelid1)
|
||||||
|
displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms
|
||||||
|
else
|
||||||
|
displayId = 17519; // world visible trigger's model
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cinfo->Modelid2)
|
||||||
|
displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players
|
||||||
|
else
|
||||||
|
displayId = 11686; // world invisible trigger's model
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldDisplayPos, uint32(displayId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNIT_DYNAMIC_FLAGS
|
||||||
|
// Hide lootable animation for unallowed players.
|
||||||
|
if (posPointers.UnitDynamicFlagsPos >= 0)
|
||||||
|
{
|
||||||
|
uint32 dynamicFlags = m_uint32Values[UNIT_DYNAMIC_FLAGS] & ~(UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER);
|
||||||
|
|
||||||
|
if (creature)
|
||||||
|
{
|
||||||
|
if (creature->hasLootRecipient())
|
||||||
|
{
|
||||||
|
dynamicFlags |= UNIT_DYNFLAG_TAPPED;
|
||||||
|
if (creature->isTappedBy(target))
|
||||||
|
dynamicFlags |= UNIT_DYNFLAG_TAPPED_BY_PLAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target->isAllowedToLoot(creature))
|
||||||
|
dynamicFlags &= ~UNIT_DYNFLAG_LOOTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
|
||||||
|
if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
|
||||||
|
if (!HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID()))
|
||||||
|
dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
|
||||||
|
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitDynamicFlagsPos, dynamicFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNIT_FIELD_BYTES_2
|
||||||
|
if (posPointers.UnitFieldBytes2Pos >= 0)
|
||||||
|
{
|
||||||
|
if (IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsInRaidWith(target))
|
||||||
|
{
|
||||||
|
FactionTemplateEntry const* ft1 = GetFactionTemplateEntry();
|
||||||
|
FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry();
|
||||||
|
if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
|
||||||
|
// Allow targetting opposite faction in party when enabled in config
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldBytes2Pos, (m_uint32Values[UNIT_FIELD_BYTES_2] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8))); // this flag is at uint8 offset 1 !!
|
||||||
|
}// pussywizard / Callmephil
|
||||||
|
else if (target->IsSpectator() && target->FindMap() && target->FindMap()->IsBattleArena() &&
|
||||||
|
(this->GetTypeId() == TYPEID_PLAYER || this->GetTypeId() == TYPEID_UNIT || this->GetTypeId() == TYPEID_DYNAMICOBJECT))
|
||||||
|
{
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldBytes2Pos, (m_uint32Values[UNIT_FIELD_BYTES_2] & 0xFFFFF2FF)); // clear UNIT_BYTE2_FLAG_PVP, UNIT_BYTE2_FLAG_FFA_PVP, UNIT_BYTE2_FLAG_SANCTUARY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNIT_FIELD_FACTIONTEMPLATE
|
||||||
|
if (posPointers.UnitFieldFactionTemplatePos >= 0)
|
||||||
|
{
|
||||||
|
if (IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsInRaidWith(target))
|
||||||
|
{
|
||||||
|
FactionTemplateEntry const* ft1 = GetFactionTemplateEntry();
|
||||||
|
FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry();
|
||||||
|
if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
|
||||||
|
// pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldFactionTemplatePos, uint32(target->GetFaction()));
|
||||||
|
}// pussywizard / Callmephil
|
||||||
|
else if (target->IsSpectator() && target->FindMap() && target->FindMap()->IsBattleArena() &&
|
||||||
|
(this->GetTypeId() == TYPEID_PLAYER || this->GetTypeId() == TYPEID_UNIT || this->GetTypeId() == TYPEID_DYNAMICOBJECT))
|
||||||
|
{
|
||||||
|
valuesUpdateBuf.put(posPointers.UnitFieldFactionTemplatePos, uint32(target->GetFaction()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sScriptMgr->OnPatchValuesUpdate(this, valuesUpdateBuf, posPointers, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown)
|
void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown)
|
||||||
|
|||||||
@@ -1321,6 +1321,62 @@ private:
|
|||||||
Unit* defaultValue;
|
Unit* defaultValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// BuildValuesCachePosPointers is marks of the position of some data inside of BuildValue cache.
|
||||||
|
struct BuildValuesCachePosPointers
|
||||||
|
{
|
||||||
|
BuildValuesCachePosPointers() :
|
||||||
|
UnitNPCFlagsPos(-1), UnitFieldAuraStatePos(-1), UnitFieldFlagsPos(-1), UnitFieldDisplayPos(-1),
|
||||||
|
UnitDynamicFlagsPos(-1), UnitFieldBytes2Pos(-1), UnitFieldFactionTemplatePos(-1) {}
|
||||||
|
|
||||||
|
void ApplyOffset(uint32 offset)
|
||||||
|
{
|
||||||
|
if (UnitNPCFlagsPos >= 0)
|
||||||
|
UnitNPCFlagsPos += offset;
|
||||||
|
|
||||||
|
if (UnitFieldAuraStatePos >= 0)
|
||||||
|
UnitFieldAuraStatePos += offset;
|
||||||
|
|
||||||
|
if (UnitFieldFlagsPos >= 0)
|
||||||
|
UnitFieldFlagsPos += offset;
|
||||||
|
|
||||||
|
if (UnitFieldDisplayPos >= 0)
|
||||||
|
UnitFieldDisplayPos += offset;
|
||||||
|
|
||||||
|
if (UnitDynamicFlagsPos >= 0)
|
||||||
|
UnitDynamicFlagsPos += offset;
|
||||||
|
|
||||||
|
if (UnitFieldBytes2Pos >= 0)
|
||||||
|
UnitFieldBytes2Pos += offset;
|
||||||
|
|
||||||
|
if (UnitFieldFactionTemplatePos >= 0)
|
||||||
|
UnitFieldFactionTemplatePos += offset;
|
||||||
|
|
||||||
|
for (auto it = other.begin(); it != other.end(); ++it)
|
||||||
|
it->second += offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 UnitNPCFlagsPos;
|
||||||
|
int32 UnitFieldAuraStatePos;
|
||||||
|
int32 UnitFieldFlagsPos;
|
||||||
|
int32 UnitFieldDisplayPos;
|
||||||
|
int32 UnitDynamicFlagsPos;
|
||||||
|
int32 UnitFieldBytes2Pos;
|
||||||
|
int32 UnitFieldFactionTemplatePos;
|
||||||
|
|
||||||
|
std::unordered_map<uint16 /*index*/, uint32 /*pos*/> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
// BuildValuesCachedBuffer cache for calculated BuildValue.
|
||||||
|
struct BuildValuesCachedBuffer
|
||||||
|
{
|
||||||
|
BuildValuesCachedBuffer(uint32 bufferSize) :
|
||||||
|
buffer(bufferSize), posPointers() {}
|
||||||
|
|
||||||
|
ByteBuffer buffer;
|
||||||
|
|
||||||
|
BuildValuesCachePosPointers posPointers;
|
||||||
|
};
|
||||||
|
|
||||||
class Unit : public WorldObject
|
class Unit : public WorldObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -2505,7 +2561,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
explicit Unit (bool isWorldObject);
|
explicit Unit (bool isWorldObject);
|
||||||
|
|
||||||
void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const override;
|
void BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) override;
|
||||||
|
|
||||||
UnitAI* i_AI, *i_disabledAI;
|
UnitAI* i_AI, *i_disabledAI;
|
||||||
|
|
||||||
@@ -2598,6 +2654,9 @@ private:
|
|||||||
[[nodiscard]] float GetCombatRatingReduction(CombatRating cr) const;
|
[[nodiscard]] float GetCombatRatingReduction(CombatRating cr) const;
|
||||||
[[nodiscard]] uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
|
[[nodiscard]] uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;
|
||||||
|
|
||||||
|
void PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPointers& posPointers, Player* target);
|
||||||
|
void InvalidateValuesUpdateCache() { _valuesUpdateCache.clear(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetFeared(bool apply, Unit* fearedBy = nullptr, bool isFear = false);
|
void SetFeared(bool apply, Unit* fearedBy = nullptr, bool isFear = false);
|
||||||
void SetConfused(bool apply);
|
void SetConfused(bool apply);
|
||||||
@@ -2635,6 +2694,9 @@ private:
|
|||||||
uint32 _lastExtraAttackSpell;
|
uint32 _lastExtraAttackSpell;
|
||||||
std::unordered_map<ObjectGuid /*guid*/, uint32 /*count*/> extraAttacksTargets;
|
std::unordered_map<ObjectGuid /*guid*/, uint32 /*count*/> extraAttacksTargets;
|
||||||
ObjectGuid _lastDamagedTargetGuid;
|
ObjectGuid _lastDamagedTargetGuid;
|
||||||
|
|
||||||
|
typedef std::unordered_map<uint64 /*visibleFlag(uint32) + updateType(uint8)*/, BuildValuesCachedBuffer> ValuesUpdateCache;
|
||||||
|
ValuesUpdateCache _valuesUpdateCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Acore
|
namespace Acore
|
||||||
|
|||||||
@@ -192,18 +192,24 @@ bool ScriptMgr::IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, By
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptMgr::OnBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player* target, uint16 index)
|
bool ScriptMgr::ShouldTrackValuesUpdatePosByIndex(Unit const* unit, uint8 updateType, uint16 index)
|
||||||
{
|
{
|
||||||
auto ret = IsValidBoolScript<UnitScript>([&](UnitScript* script) { return script->OnBuildValuesUpdate(unit, updateType, fieldBuffer, target, index); });
|
auto ret = IsValidBoolScript<UnitScript>([&](UnitScript* script) { return script->ShouldTrackValuesUpdatePosByIndex(unit, updateType, index); });
|
||||||
|
|
||||||
if (ret && *ret)
|
if (ret && *ret)
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnPatchValuesUpdate(Unit const* unit, ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPointers& posPointers, Player* target)
|
||||||
|
{
|
||||||
|
ExecuteScript<UnitScript>([&](UnitScript* script)
|
||||||
|
{
|
||||||
|
script->OnPatchValuesUpdate(unit, valuesUpdateBuf, posPointers, target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnUnitUpdate(Unit* unit, uint32 diff)
|
void ScriptMgr::OnUnitUpdate(Unit* unit, uint32 diff)
|
||||||
{
|
{
|
||||||
ExecuteScript<UnitScript>([&](UnitScript* script)
|
ExecuteScript<UnitScript>([&](UnitScript* script)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
enum ReputationRank : uint8;
|
enum ReputationRank : uint8;
|
||||||
class ByteBuffer;
|
class ByteBuffer;
|
||||||
|
struct BuildValuesCachePosPointers;
|
||||||
|
|
||||||
class UnitScript : public ScriptObject
|
class UnitScript : public ScriptObject
|
||||||
{
|
{
|
||||||
@@ -69,7 +70,9 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] virtual bool IsCustomBuildValuesUpdate(Unit const* /*unit*/, uint8 /*updateType*/, ByteBuffer& /*fieldBuffer*/, Player const* /*target*/, uint16 /*index*/) { return false; }
|
[[nodiscard]] virtual bool IsCustomBuildValuesUpdate(Unit const* /*unit*/, uint8 /*updateType*/, ByteBuffer& /*fieldBuffer*/, Player const* /*target*/, uint16 /*index*/) { return false; }
|
||||||
|
|
||||||
[[nodiscard]] virtual bool OnBuildValuesUpdate(Unit const* /*unit*/, uint8 /*updateType*/, ByteBuffer& /*fieldBuffer*/, Player* /*target*/, uint16 /*index*/) { return false; }
|
[[nodiscard]] virtual bool ShouldTrackValuesUpdatePosByIndex(Unit const* /*unit*/, uint8 /*updateType*/, uint16 /*index*/) { return false; }
|
||||||
|
|
||||||
|
virtual void OnPatchValuesUpdate(Unit const* /*unit*/, ByteBuffer& /*valuesUpdateBuf*/, BuildValuesCachePosPointers& /*posPointers*/, Player* /*target*/) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This hook runs in Unit::Update
|
* @brief This hook runs in Unit::Update
|
||||||
|
|||||||
@@ -548,7 +548,8 @@ public: /* UnitScript */
|
|||||||
bool IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
|
bool IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
|
||||||
bool CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update);
|
bool CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update);
|
||||||
bool IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player const* target, uint16 index);
|
bool IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player const* target, uint16 index);
|
||||||
bool OnBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player* target, uint16 index);
|
bool ShouldTrackValuesUpdatePosByIndex(Unit const* unit, uint8 updateType, uint16 index);
|
||||||
|
void OnPatchValuesUpdate(Unit const* unit, ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPointers& posPointers, Player* target);
|
||||||
void OnUnitUpdate(Unit* unit, uint32 diff);
|
void OnUnitUpdate(Unit* unit, uint32 diff);
|
||||||
void OnDisplayIdChange(Unit* unit, uint32 displayId);
|
void OnDisplayIdChange(Unit* unit, uint32 displayId);
|
||||||
void OnUnitEnterEvadeMode(Unit* unit, uint8 why);
|
void OnUnitEnterEvadeMode(Unit* unit, uint8 why);
|
||||||
|
|||||||
Reference in New Issue
Block a user