diff options
-rw-r--r-- | src/game/BattleGround.cpp | 4 | ||||
-rw-r--r-- | src/game/GroupHandler.cpp | 26 | ||||
-rw-r--r-- | src/game/Pet.cpp | 2 | ||||
-rw-r--r-- | src/game/Pet.h | 9 | ||||
-rw-r--r-- | src/game/Player.cpp | 59 | ||||
-rw-r--r-- | src/game/Player.h | 7 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 204 | ||||
-rw-r--r-- | src/game/SpellAuras.h | 19 | ||||
-rw-r--r-- | src/game/Unit.cpp | 73 | ||||
-rw-r--r-- | src/game/Unit.h | 34 |
10 files changed, 248 insertions, 189 deletions
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 9669f638fc3..0fa7f09aa20 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1407,7 +1407,9 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID()); // aura - pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL); + //TODO: Fix display here + //pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL); + //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009); //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C); //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF); diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index 6bcc4a4d8cc..574ebd7de75 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -726,18 +726,15 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke if (mask & GROUP_UPDATE_FLAG_AURAS) { - const uint64& auramask = player->GetAuraUpdateMask(); + const uint64& auramask = player->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { - uint32 updatedAura = player->GetVisibleAura(i); - *data << uint32(updatedAura); + AuraSlotEntry * pAura = player->GetVisibleAura(i); + *data << uint32(pAura ? pAura->m_spellId : 0); *data << uint8(1); - //TODO: find a safe place to do this cleanup - //if(!updatedAura) - //player->UnsetAuraUpdateMask(i); } } } @@ -811,18 +808,15 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(pet) { - const uint64& auramask = pet->GetAuraUpdateMask(); + const uint64& auramask = pet->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { - uint32 updatedAura = pet->GetVisibleAura(i); - *data << uint32(updatedAura); + AuraSlotEntry * pAura = pet->GetVisibleAura(i); + *data << uint32(pAura ? pAura->m_spellId : 0); *data << uint8(1); - //TODO: find a safe place to do this cleanup - //if(!updatedAura) - //pet->UnsetAuraUpdateMask(i); } } } @@ -880,10 +874,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) auramask; // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { - if(uint32 aura = player->GetVisibleAura(i)) + if(AuraSlotEntry * pAura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); - data << (uint32) aura; + data << (uint32) pAura->m_spellId; data << (uint8) 1; } } @@ -906,10 +900,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) petauramask; // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { - if(uint32 petaura = pet->GetVisibleAura(i)) + if(AuraSlotEntry * pAura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); - data << (uint32) petaura; + data << (uint32) pAura->m_spellId; data << (uint8) 1; } } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 8dcea866ef4..1205ed641f0 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -43,7 +43,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] = Pet::Pet(PetType type) : Creature(), m_petType(type), m_removed(false), m_happinessTimer(7500), m_duration(0), m_bonusdamage(0), -m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false), +m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL) { m_isPet = true; diff --git a/src/game/Pet.h b/src/game/Pet.h index 4425f2e06db..f863051b74d 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -216,10 +216,9 @@ class Pet : public Creature time_t m_resetTalentsTime; uint32 m_usedTalentCount; - const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } - void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } - void UnsetAuraUpdateMask(uint8 slot) { m_auraUpdateMask &= ~(uint64(1) << slot); } - void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } + const uint64& GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; } + void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); } + void ResetAuraUpdateMaskForRaid() { m_auraRaidUpdateMask = 0; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } @@ -229,7 +228,7 @@ class Pet : public Creature PetType m_petType; int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) int32 m_bonusdamage; - uint64 m_auraUpdateMask; + uint64 m_auraRaidUpdateMask; bool m_loading; DeclinedName *m_declinedname; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 082e4bc41a7..8a2a9982d4e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -328,7 +328,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) // group is initialized in the reference constructor SetGroupInvite(NULL); m_groupUpdateMask = 0; - m_auraUpdateMask = 0; + m_auraRaidUpdateMask = 0; duel = NULL; @@ -4020,8 +4020,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) { if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,i)) { - Aur->SetAuraDuration(delta*1000); - Aur->SendAuraUpdate(false); + Aur->SetAuraDurationAndUpdate(delta*1000); } } } @@ -18699,9 +18698,9 @@ void Player::SendUpdateToOutOfRangeGroupMembers() group->UpdatePlayerOutOfRange(this); m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE; - m_auraUpdateMask = 0; + m_auraRaidUpdateMask = 0; if(Pet *pet = GetPet()) - pet->ResetAuraUpdateMask(); + pet->ResetAuraUpdateMaskForRaid(); } void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) @@ -18926,35 +18925,39 @@ void Player::SendAurasForTarget(Unit *target) Unit::VisibleAuraMap const *visibleAuras = target->GetVisibleAuras(); for(Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) { - for(uint32 j = 0; j < 3; ++j) + Aura * aura=NULL; + for (uint8 i=0 ; i<3; i++) { - if(Aura *aura = target->GetAura(itr->second, j)) + if (itr->second.m_slotAuras[i]) { - data << uint8(aura->GetAuraSlot()); - data << uint32(aura->GetId()); + aura=itr->second.m_slotAuras[i]; + break; + } + } + if(aura) + { + data << uint8(aura->GetAuraSlot()); + data << uint32(aura->GetId()); - if(aura->GetId()) + if(aura->GetId()) + { + // flags + data << itr->second.m_Flags; + // level + data << itr->second.m_Level; + // charges + data << uint8(aura->GetAuraCharges()); + + if(!(itr->second.m_Flags & AFLAG_NOT_CASTER)) { - uint8 auraFlags = aura->GetAuraFlags(); - // flags - data << uint8(auraFlags); - // level - data << uint8(aura->GetAuraLevel()); - // charges - data << uint8(aura->GetAuraCharges()); - - if(!(auraFlags & AFLAG_NOT_CASTER)) - { - data << uint8(0); // packed GUID of someone (caster?) - } + data << uint8(0); // packed GUID of someone (caster?) + } - if(auraFlags & AFLAG_DURATION) // include aura duration - { - data << uint32(aura->GetAuraMaxDuration()); - data << uint32(aura->GetAuraDuration()); - } + if(itr->second.m_Flags & AFLAG_DURATION) // include aura duration + { + data << uint32(aura->GetAuraMaxDuration()); + data << uint32(aura->GetAuraDuration()); } - break; } } } diff --git a/src/game/Player.h b/src/game/Player.h index eeac9ca53f0..186d0b5692c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2142,9 +2142,8 @@ class TRINITY_DLL_SPEC Player : public Unit uint8 GetSubGroup() const { return m_group.getSubGroup(); } uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; } void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; } - const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } - void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } - void UnsetAuraUpdateMask(uint8 slot) { m_auraUpdateMask &= ~(uint64(1) << slot); } + const uint64& GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; } + void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); } Player* GetNextRandomRaidMember(float radius); PartyResult CanUninviteFromGroup() const; @@ -2390,7 +2389,7 @@ class TRINITY_DLL_SPEC Player : public Unit GroupReference m_group; Group *m_groupInvite; uint32 m_groupUpdateMask; - uint64 m_auraUpdateMask; + uint64 m_auraRaidUpdateMask; // Temporarily removed pet cache uint32 m_temporaryUnsummonedPetNumber; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index a2155e6df72..d44101cf68e 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -769,12 +769,21 @@ void Aura::_AddAura() if(!m_target) return; + Unit* caster = GetCaster(); + + // passive auras (except totem auras) do not get placed in the slots + // area auras with SPELL_AURA_NONE are not shown on target + // all further code applies only to active spells + if(!((m_spellProto->Attributes & 0x80 || !m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && + (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))) + return; + // Second aura if some spell bool secondaura = false; // Try find slot for aura uint8 slot = NULL_AURA_SLOT; - // Lookup for some spell auras (and get slot from it) - for(uint8 i = 0; i < m_effIndex; i++) + // Lookup for auras already applied from spell + for(uint8 i = 0; i < 3; i++) { Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) @@ -791,7 +800,7 @@ void Aura::_AddAura() break; } // Lookup free slot - if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS) + if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS ) { Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); for(uint8 i = 0; i < MAX_AURAS; ++i) @@ -800,71 +809,82 @@ void Aura::_AddAura() if(itr == visibleAuras->end()) { slot = i; - // update for out of range group members (on 1 slot use) - m_target->UpdateAuraForGroup(slot); break; } } } - Unit* caster = GetCaster(); + if (!secondaura) + { + AuraSlotEntry t_entry; + t_entry.m_Flags=(IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE); + t_entry.m_Level=(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - // passive auras (except totem auras) do not get placed in the slots - // area auras with SPELL_AURA_NONE are not shown on target - if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && - (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) + //init pointers-prevent unexpected behaviour + for(uint8 i = 0; i < 3; i++) + t_entry.m_slotAuras[i]=NULL; + + t_entry.m_Level=(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + m_target->SetVisibleAura(slot, t_entry); + } + + sLog.outError("aura::_addaura slot:%d", slot); + + AuraSlotEntry * entry; + entry=m_target->GetVisibleAura(slot); + + entry->m_Flags |= (1 << GetEffIndex()); + entry->m_slotAuras[GetEffIndex()]=this; + + SetAuraSlot( slot ); + + if(slot < MAX_AURAS) // slot found send data to client { - SetAuraSlot( slot ); - if(slot < MAX_AURAS) // slot found send data to client - { - SetAura(false); - SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE)); - SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - SendAuraUpdate(false); - } + // update for out of range group members (on 1 slot use) + m_target->UpdateAuraForGroup(slot); + } - //***************************************************** - // Update target aura state flag (at 1 aura apply) - // TODO: Make it easer - //***************************************************** - if (!secondaura) - { - // Sitdown on apply aura req seated - if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState()) - m_target->SetStandState(UNIT_STAND_STATE_SIT); + //***************************************************** + // Update target aura state flag (at 1 aura apply) + // TODO: Make it easer + //***************************************************** + if (!secondaura) + { + // Sitdown on apply aura req seated + if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState()) + m_target->SetStandState(UNIT_STAND_STATE_SIT); - // register aura diminishing on apply - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),true); + // register aura diminishing on apply + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),true); - // Update Seals information - if (IsSealSpell(m_spellProto)) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); + // Update Seals information + if (IsSealSpell(m_spellProto)) + m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); - // Conflagrate aura state on Immolate - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[0] & 4) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); + // Conflagrate aura state on Immolate + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[0] & 4) + m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); - // Faerie Fire (druid versions) - if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x400) - m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true); + // Faerie Fire (druid versions) + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x400) + m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true); - // Victorious - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00040000) - m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true); + // Victorious + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00040000) + m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true); - // Swiftmend state on Regrowth & Rejuvenation - if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x50 ) - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); + // Swiftmend state on Regrowth & Rejuvenation + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x50 ) + m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); - // Deadly poison aura state - if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x10000) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true); + // Deadly poison aura state + if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x10000) + m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true); - // Enrage aura state - if(m_spellProto->Dispel == DISPEL_ENRAGE) - m_target->ModifyAuraState(AURA_STATE_ENRAGE, true); - } + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + m_target->ModifyAuraState(AURA_STATE_ENRAGE, true); } } @@ -894,39 +914,31 @@ void Aura::_RemoveAura() if(slot >= MAX_AURAS) // slot not set return; - if(m_target->GetVisibleAura(slot) == 0) + if(!m_target->GetVisibleAura(slot)) //slot already removed-shouldn't happen return; bool lastaura = true; - // find other aura in same slot (current already removed from list) - for(uint8 i = 0; i < 3; i++) + AuraSlotEntry * entry=m_target->GetVisibleAura(slot); + + entry->m_slotAuras[GetEffIndex()]=NULL; //unregister aura + Aura * ptr= NULL; + for (uint8 i=0 ; i<3; i++) //check slot for more auras of the spell { - Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); - for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) + if (entry->m_slotAuras[i]) { - if(itr->second->GetAuraSlot()==slot) - { - lastaura = false; - break; - } - } - if(!lastaura) + ptr=entry->m_slotAuras[i]; break; + } } // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (lastaura) + if(!ptr) { // unregister aura diminishing (and store last time) if (getDiminishGroup() != DIMINISHING_NONE ) m_target->ApplyDiminishingAura(getDiminishGroup(),false); - SetAura(true); - SetAuraFlags(AFLAG_NONE); - SetAuraLevel(0); - SendAuraUpdate(true); - // update for out of range group members m_target->UpdateAuraForGroup(slot); @@ -996,38 +1008,6 @@ void Aura::_RemoveAura() } } -void Aura::SendAuraUpdate(bool remove) -{ - WorldPacket data(SMSG_AURA_UPDATE); - data.append(m_target->GetPackGUID()); - data << uint8(GetAuraSlot()); - data << uint32(remove ? 0 : GetId()); - - if(remove) - { - m_target->SendMessageToSet(&data, true); - return; - } - - uint8 auraFlags = GetAuraFlags(); - data << uint8(auraFlags); - data << uint8(GetAuraLevel()); - data << uint8(m_procCharges ? m_procCharges : m_stackAmount); - - if(!(auraFlags & AFLAG_NOT_CASTER)) - { - data << uint8(0); // pguid - } - - if(auraFlags & AFLAG_DURATION) - { - data << uint32(GetAuraMaxDuration()); - data << uint32(GetAuraDuration()); - } - - m_target->SendMessageToSet(&data, true); -} - void Aura::SetStackAmount(uint8 stackAmount) { if (stackAmount != m_stackAmount) @@ -1073,7 +1053,11 @@ bool Aura::modStackAmount(int32 num) void Aura::RefreshAura() { m_duration = m_maxduration; - SendAuraUpdate(false); + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { + // update for out of range group members (on 1 slot use) + m_target->UpdateAuraForGroup(GetAuraSlot()); + } } bool Aura::isAffectedOnSpell(SpellEntry const *spell) const @@ -5780,13 +5764,13 @@ void Aura::PeriodicTick() int32 gain = pCaster->ModifyPower(power,gain_amount); m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); } - // Mark of Kaz'rogal - if(GetId() == 31447 && m_target->GetPower(power) == 0) - { - m_target->CastSpell(m_target, 31463, true, 0, this); - // Remove aura - SetAuraDuration(0); - } + // Mark of Kaz'rogal + if(GetId() == 31447 && m_target->GetPower(power) == 0) + { + m_target->CastSpell(m_target, 31463, true, 0, this); + // Remove aura + SetAuraDuration(0); + } break; } case SPELL_AURA_PERIODIC_ENERGIZE: diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index e3f4e6ac6b0..06bbc22af12 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -230,6 +230,12 @@ class TRINITY_DLL_SPEC Aura void SetAuraMaxDuration(int32 duration) { m_maxduration = duration; } int32 GetAuraDuration() const { return m_duration; } void SetAuraDuration(int32 duration) { m_duration = duration; } + void SetAuraDurationAndUpdate(int32 duration) + { + m_duration = duration; + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { m_target->UpdateAuraForGroup(GetAuraSlot()); } + } time_t GetAuraApplyTime() { return m_applyTime; } SpellModifier *getAuraSpellMod() {return m_spellmod; } @@ -249,30 +255,25 @@ class TRINITY_DLL_SPEC Aura uint8 GetAuraSlot() const { return m_auraSlot; } void SetAuraSlot(uint8 slot) { m_auraSlot = slot; } - uint8 GetAuraFlags() const { return m_auraFlags; } - void SetAuraFlags(uint8 flags) { m_auraFlags = flags; } - uint8 GetAuraLevel() const { return m_auraLevel; } - void SetAuraLevel(uint8 level) { m_auraLevel = level; } uint8 GetAuraCharges() const { return m_procCharges; } void SetAuraCharges(uint8 charges) { if (m_procCharges == charges) return; m_procCharges = charges; - SendAuraUpdate(false); + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { m_target->UpdateAuraForGroup(GetAuraSlot()); } } bool DropAuraCharge() // return true if last charge dropped { if (m_procCharges == 0) return false; m_procCharges--; - SendAuraUpdate(false); + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { m_target->UpdateAuraForGroup(GetAuraSlot()); } return m_procCharges == 0; } - void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); } - void SendAuraUpdate(bool remove); - int8 GetStackAmount() {return m_stackAmount;} //int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;} void SetStackAmount(uint8 num); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5fcec4dff84..5960cde6309 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -94,6 +94,7 @@ Unit::Unit() m_state = 0; m_form = FORM_NONE; m_deathState = ALIVE; + uint64 m_auraUpdateMask; for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) m_currentSpells[i] = NULL; @@ -207,6 +208,18 @@ void Unit::Update( uint32 p_time ) _UpdateAura(); }else m_AurasCheck -= p_time;*/ + const uint64& auramask = GetAuraUpdateMask(); + if (auramask) + { + for(uint32 i = 0; i < MAX_AURAS; ++i) + { + if(auramask & (uint64(1) << i)) + { + SendAuraUpdate(i); + } + } + ResetAuraUpdateMask(); + } // WARNING! Order of execution here is important, do not change. // Spells must be processed with event system BEFORE they go to _UpdateSpells. @@ -4163,7 +4176,11 @@ void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime) iter->second->SetAuraDuration(0); else iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime); - iter->second->SendAuraUpdate(false); + if(iter->second->GetAuraSlot() < MAX_AURAS) // slot found send data to client + { + // update for out of range group members (on 1 slot use) + UpdateAuraForGroup(iter->second->GetAuraSlot()); + } sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration()); } } @@ -11538,7 +11555,7 @@ void Unit::UpdateAuraForGroup(uint8 slot) if(player->GetGroup()) { player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS); - player->SetAuraUpdateMask(slot); + player->SetAuraUpdateMaskForRaid(slot); } } else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) @@ -11550,10 +11567,11 @@ void Unit::UpdateAuraForGroup(uint8 slot) if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) { ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS); - pet->SetAuraUpdateMask(slot); + pet->SetAuraUpdateMaskForRaid(slot); } } } + SetAuraUpdateMask(slot); } float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) @@ -12464,6 +12482,55 @@ void Unit::GetPartyMember(std::list<Unit*> &TagUnitMap, float radius) } } +void Unit::SendAuraUpdate(uint8 slot) +{ + WorldPacket data(SMSG_AURA_UPDATE); + + Aura * ptr=NULL; + VisibleAuraMap const *visibleAuras = GetVisibleAuras(); + AuraSlotEntry * entry=GetVisibleAura(slot); + if (!entry) + return; + + //Get pointer to first aura-it doesn't matter which one we use (at least it shouldn't) + for (uint8 i=0 ; i<3; i++) + { + if (entry->m_slotAuras[i]) + { + ptr=entry->m_slotAuras[i]; + break; + } + } + + data.append(GetPackGUID()); + data << uint8(slot); + data << uint32(ptr ? ptr->GetId() : 0); + + if(!ptr) + { + RemoveVisibleAura(slot); + SendMessageToSet(&data, true); + return; + } + + data << uint8(entry->m_Flags); + data << uint8(entry->m_Level); + data << uint8(ptr->GetAuraCharges()? ptr->GetAuraCharges() : ptr->GetStackAmount()); + + if(!(entry->m_Flags & AFLAG_NOT_CASTER)) + { + data << uint8(0); // pguid + } + + if(entry->m_Flags & AFLAG_DURATION) + { + data << uint32(ptr->GetAuraMaxDuration()); + data << uint32(ptr->GetAuraDuration()); + } + + SendMessageToSet(&data, true); +} + void Unit::AddAura(uint32 spellId, Unit* target) { if(!target || !target->isAlive()) diff --git a/src/game/Unit.h b/src/game/Unit.h index bd61171de9b..181efff1571 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -806,6 +806,14 @@ enum ReactiveType #define MAX_REACTIVE 3 #define MAX_TOTEM 4 +struct AuraSlotEntry +{ + uint8 m_Flags; + uint8 m_Level; + uint32 m_spellId; + Aura * m_slotAuras[3]; +}; + // delay time next attack to prevent client attack animation problems #define ATTACK_DISPLAY_DELAY 200 @@ -820,7 +828,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject typedef std::list<Aura *> AuraList; typedef std::list<DiminishingReturn> Diminishing; typedef std::set<uint32> ComboPointHolderSet; - typedef std::map<uint8, uint32> VisibleAuraMap; + + typedef std::map<uint8, AuraSlotEntry> VisibleAuraMap; virtual ~Unit ( ); @@ -1332,22 +1341,22 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ } HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } - uint32 GetVisibleAura(uint8 slot) + VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; } + uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); } + AuraSlotEntry * GetVisibleAura(uint8 slot) { VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); if(itr != m_visibleAuras.end()) - return itr->second; + return &itr->second; return 0; } - void SetVisibleAura(uint8 slot, uint32 spellid) - { - if(spellid == 0) - m_visibleAuras.erase(slot); - else - m_visibleAuras[slot] = spellid; - } - VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; } - uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); } + void SetVisibleAura(uint8 slot, AuraSlotEntry entry) { m_visibleAuras[slot] = entry; } + void RemoveVisibleAura(uint8 slot) { m_visibleAuras.erase(slot); } + + const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } + void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } + void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } + void SendAuraUpdate(uint8 slot); Aura* GetAura(uint32 spellId, uint32 effindex); Aura* GetAura(AuraType type, uint32 family, uint32 familyFlag1 = 0, uint32 familyFlag2 = 0, uint32 familyFlag3 = 0, uint64 casterGUID = 0); @@ -1523,6 +1532,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject DeathState m_deathState; + uint64 m_auraUpdateMask; AuraMap m_Auras; typedef std::list<uint64> DynObjectGUIDs; |