Skip to content

Commit

Permalink
Aura/Spell: Rework aura protocol more closely based on discovered new…
Browse files Browse the repository at this point in the history
… info
  • Loading branch information
killerwife committed Aug 15, 2023
1 parent 0c08098 commit c3a63ac
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 46 deletions.
31 changes: 23 additions & 8 deletions src/game/Entities/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19782,18 +19782,13 @@ void Player::SendAuraDurationsForTarget(Unit* target)
if (holder->GetAuraSlot() >= MAX_AURAS || holder->IsPassive() || holder->GetCasterGuid() != GetObjectGuid())
continue;

holder->SendAuraDurationForCaster(this);
holder->SendAuraDurationToCaster(this);
}
}

void Player::SendAuraDurationsOnLogin(bool visible)
{
if (!visible)
{
WorldPacket data(SMSG_SET_EXTRA_AURA_INFO, 8);
data << GetPackGUID();
SendDirectMessage(data);
}
std::vector<SpellAuraHolder*> holders;

uint32 counter = MAX_AURAS;
SpellAuraHolderMap const& auraHolders = GetSpellAuraHolderMap();
Expand All @@ -19813,9 +19808,29 @@ void Player::SendAuraDurationsOnLogin(bool visible)
continue;
}

holder->SendAuraDurationForTarget(!visible ? counter : MAX_AURAS);
holders.push_back(holder);
++counter;
}

if (!visible) // slots >= 56 are sent as singles
{
std::sort(holders.begin(), holders.end(), [](SpellAuraHolder* left, SpellAuraHolder* right) { return left->GetAuraSlot() > right->GetAuraSlot(); });
for (SpellAuraHolder* holder : holders)
holder->SendAuraDurationToCaster(this);
}
else // visible slots (<= 56) are sent in a single packet
{
WorldPacket data(SMSG_INIT_EXTRA_AURA_INFO, (8 + (1 + 4 + 4 + 4) * holders.size()));
data << GetPackGUID();
for (SpellAuraHolder* holder : holders)
{
data << uint8(holder->GetAuraSlot());
data << uint32(holder->GetId());
data << uint32(holder->GetAuraMaxDuration());
data << uint32(holder->GetAuraDuration());
}
SendDirectMessage(data);
}
}

ItemSetEffect* Player::GetItemSetEffect(uint32 setId)
Expand Down
2 changes: 1 addition & 1 deletion src/game/Entities/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5771,7 +5771,7 @@ void Unit::DelaySpellAuraHolder(uint32 spellId, int32 delaytime, ObjectGuid cast
else
holder->SetAuraDuration(holder->GetAuraDuration() - delaytime);

holder->UpdateAuraDuration();
holder->ForceUpdateAuraDuration();

DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell %u partially interrupted on %s, new duration: %u ms", spellId, GetGuidStr().c_str(), holder->GetAuraDuration());
}
Expand Down
27 changes: 15 additions & 12 deletions src/game/Spells/Spell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7168,23 +7168,26 @@ void Spell::DelayedChannel()

DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell %u partially interrupted for %i ms, new duration: %u ms", m_spellInfo->Id, delaytime, m_timer);

for (TargetList::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
SendChannelUpdate(m_timer);

if (m_timer != 0) // must be after channel update
{
if ((*ihit).missCondition == SPELL_MISS_NONE)
for (auto& target : m_UniqueTargetInfo)
{
if (Unit* unit = m_caster->GetObjectGuid() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID))
unit->DelaySpellAuraHolder(m_spellInfo->Id, delaytime, m_caster->GetObjectGuid());
if (target.missCondition == SPELL_MISS_NONE)
{
if (Unit* unit = m_caster->GetObjectGuid() == target.targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target.targetGUID))
unit->DelaySpellAuraHolder(m_spellInfo->Id, delaytime, m_caster->GetObjectGuid());
}
}
}

for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
{
// partially interrupt persistent area auras
if (DynamicObject* dynObj = m_caster->GetDynObject(m_spellInfo->Id, SpellEffectIndex(j)))
dynObj->Delay(delaytime);
for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
{
// partially interrupt persistent area auras
if (DynamicObject* dynObj = m_caster->GetDynObject(m_spellInfo->Id, SpellEffectIndex(j)))
dynObj->Delay(delaytime);
}
}

SendChannelUpdate(m_timer);
}

void Spell::UpdateOriginalCasterPointer()
Expand Down
89 changes: 66 additions & 23 deletions src/game/Spells/SpellAuras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7913,10 +7913,34 @@ void SpellAuraHolder::_AddSpellAuraHolder()
}
}

if (slot >= MAX_AURAS)
{
uint32 theoreticalSlot = MAX_AURAS;
std::set<uint32> freeSlot;
for (auto& data : m_target->GetSpellAuraHolderMap())
{
SpellAuraHolder* holder = data.second;
if (holder->GetAuraSlot() >= MAX_AURAS)
freeSlot.insert(holder->GetAuraSlot());
}
for (uint32 slot : freeSlot)
{
// set is sorted so this should yield first empty
if (theoreticalSlot == slot)
theoreticalSlot++;
else
break;
}
// slot is uint8 - avoid shenanigans - 56 max visible auras - 255 max all auras
if (theoreticalSlot > NULL_AURA_SLOT)
theoreticalSlot = NULL_AURA_SLOT;
slot = theoreticalSlot;
}

SetAuraSlot(slot);

// Not update fields for not first spell's aura, all data already in fields
if (slot < MAX_AURAS) // slot found
if (slot < MAX_AURAS) // slot found
{
SetAura(slot, false);
SetAuraFlag(slot, true);
Expand All @@ -7928,6 +7952,8 @@ void SpellAuraHolder::_AddSpellAuraHolder()

UpdateAuraDuration();
}
else if (m_target == caster && caster->IsPlayer()) // if slot >= MAX_AURAS only this is sent to target
SendAuraDurationToCaster(static_cast<Player*>(caster));

//*****************************************************
// Update target aura state flag (at 1 aura apply)
Expand Down Expand Up @@ -8736,33 +8762,53 @@ void SpellAuraHolder::ClearExtraAuraInfo(Unit* caster)

void SpellAuraHolder::UpdateAuraDuration()
{
if (GetAuraSlot() >= MAX_AURAS || m_isPassive)
if (GetAuraSlot() >= MAX_AURAS)
return;

if (m_target->IsPlayer())
// not send in case player loading - on load is sent differently
if (m_target->IsPlayer() && static_cast<Player*>(m_target)->GetSession()->PlayerLoading())
return;

Unit* caster = GetCaster();

if (!GetSpellProto()->HasAttribute(SPELL_ATTR_EX5_DO_NOT_DISPLAY_DURATION))
{
if (!GetSpellProto()->HasAttribute(SPELL_ATTR_EX5_DO_NOT_DISPLAY_DURATION))
{
WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5);
data << uint8(GetAuraSlot());
data << uint32(GetAuraDuration());
static_cast<Player*>(m_target)->SendDirectMessage(data);
// if caster == target and player, meant to get both
SendAuraDuration();

SendAuraDurationForTarget();
}
if (caster && caster->IsPlayer())
SendAuraDurationToCaster(static_cast<Player*>(caster));
}
}

// not send in case player loading (will not work anyway until player not added to map), sent in visibility change code
if (m_target->GetTypeId() == TYPEID_PLAYER && static_cast<Player*>(m_target)->GetSession()->PlayerLoading())
void SpellAuraHolder::ForceUpdateAuraDuration()
{
if (GetAuraSlot() >= MAX_AURAS)
return;

Unit* caster = GetCaster();
if (!GetSpellProto()->HasAttribute(SPELL_ATTR_EX5_DO_NOT_DISPLAY_DURATION))
{
// if caster == target and player, meant to get both
SendAuraDuration();

if (caster && caster->IsPlayer())
SendAuraDurationToCasterNeedUpdate(static_cast<Player*>(caster));
}
}

void SpellAuraHolder::SendAuraDuration()
{
if (!m_target->IsPlayer())
return;

if (caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target)
SendAuraDurationForCaster(static_cast<Player*>(caster));
WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5);
data << uint8(GetAuraSlot());
data << uint32(GetAuraDuration());
static_cast<Player*>(m_target)->SendDirectMessage(data);
}

void SpellAuraHolder::SendAuraDurationForTarget(uint32 slot)
void SpellAuraHolder::SendAuraDurationToCaster(Player* caster, uint32 slot)
{
WorldPacket data(SMSG_SET_EXTRA_AURA_INFO, (8 + 1 + 4 + 4 + 4));
data << m_target->GetPackGUID();
Expand All @@ -8771,20 +8817,17 @@ void SpellAuraHolder::SendAuraDurationForTarget(uint32 slot)
data << uint32(GetAuraMaxDuration());
data << uint32(GetAuraDuration());

static_cast<Player*>(m_target)->SendDirectMessage(data);
caster->SendDirectMessage(data);
}

void SpellAuraHolder::SendAuraDurationForCaster(Player* caster)
void SpellAuraHolder::SendAuraDurationToCasterNeedUpdate(Player* caster)
{
WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8 + 1 + 4 + 4 + 4));
data << m_target->GetPackGUID();
data << uint8(GetAuraSlot());
data << uint32(GetId());
if (!GetSpellProto()->HasAttribute(SPELL_ATTR_EX5_DO_NOT_DISPLAY_DURATION))
{
data << uint32(GetAuraMaxDuration()); // full
data << uint32(GetAuraDuration()); // remain
}
data << uint32(GetAuraMaxDuration()); // full
data << uint32(GetAuraDuration()); // remain
caster->GetSession()->SendPacket(data);
}

Expand Down
6 changes: 4 additions & 2 deletions src/game/Spells/SpellAuras.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ class SpellAuraHolder
bool IsDispellableByMask(uint32 dispelMask, Unit const* caster, SpellEntry const* spellInfo) const;

void UpdateAuraDuration();
void SendAuraDurationForTarget(uint32 slot = MAX_AURAS);
void SendAuraDurationForCaster(Player* caster);
void ForceUpdateAuraDuration();
void SendAuraDuration();
void SendAuraDurationToCaster(Player* caster, uint32 slot = MAX_AURAS);
void SendAuraDurationToCasterNeedUpdate(Player* caster);

void SetAura(uint32 slot, bool remove) { m_target->SetUInt32Value(UNIT_FIELD_AURA + slot, remove ? 0 : GetId()); }
void SetAuraFlag(uint32 slot, bool add);
Expand Down

0 comments on commit c3a63ac

Please sign in to comment.