diff options
-rw-r--r-- | src/game/Object.cpp | 19 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 4 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 79 | ||||
-rw-r--r-- | src/game/SpellAuras.h | 3 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 57 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 1 | ||||
-rw-r--r-- | src/game/Unit.cpp | 70 | ||||
-rw-r--r-- | src/game/Unit.h | 4 |
8 files changed, 150 insertions, 87 deletions
diff --git a/src/game/Object.cpp b/src/game/Object.cpp index abf4de09275..53f98214703 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -477,6 +477,13 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask if (((GameObject*)this)->GetGoArtKit()) updateMask->SetBit(GAMEOBJECT_BYTES_1); } + else if (isType(TYPEMASK_UNIT)) + { + if( ((Unit*)this)->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)) + { + updateMask->SetBit(UNIT_FIELD_AURASTATE); + } + } } else // case UPDATETYPE_VALUES { @@ -489,6 +496,13 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask updateMask->SetBit(GAMEOBJECT_DYNAMIC); updateMask->SetBit(GAMEOBJECT_BYTES_1); } + else if (isType(TYPEMASK_UNIT)) + { + if( ((Unit*)this)->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)) + { + updateMask->SetBit(UNIT_FIELD_AURASTATE); + } + } } WPAssert(updateMask && updateMask->GetCount() == m_valuesCount); @@ -513,6 +527,11 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *data << uint32(appendValue); } + else if (index == UNIT_FIELD_AURASTATE) + { + // Check per caster aura states to not enable using a pell in client if specified aura is not by target + *data << ((Unit*)this)->BuildAuraStateUpdateForTarget(target); + } // 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) { diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 535664462a5..957ef4449a6 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -893,6 +893,7 @@ enum SpellCastResult enum AuraState { // (C) used in caster aura state (T) used in target aura state // (c) used in caster aura state-not (t) used in target aura state-not + AURA_STATE_NONE = 0, // C | AURA_STATE_DEFENSE = 1, // C | AURA_STATE_HEALTHLESS_20_PERCENT = 2, // CcT | AURA_STATE_BERSERKING = 3, // C T | @@ -920,6 +921,9 @@ enum AuraState AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | }; +#define PER_CASTER_AURA_STATE_MASK ( \ + (1<<(AURA_STATE_CONFLAGRATE-1))|(1<<(AURA_STATE_SWIFTMEND-1))|(1<<(AURA_STATE_DEADLY_POISON-1))) + // Spell mechanics enum Mechanics { diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index df55a4fc1be..6ac842128b7 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -354,7 +354,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= Aura::Aura(SpellEntry const* spellproto, uint32 effMask, int32 *currentBasePoints, Unit *target, WorldObject *source, Unit *caster, Item* castItem) : m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target), m_timeCla(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), -m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_isRemoved(false) +m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1), m_updated(false), m_isRemoved(false) { assert(target); @@ -369,8 +369,6 @@ m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_aura m_isPassive = IsPassiveSpell(GetId()); - m_auraStateMask = 0; - m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto); m_applyTime = time(NULL); @@ -1195,65 +1193,6 @@ void Aura::_AddAura() } } - //***************************************************** - // Update target aura state flag - //***************************************************** - - // Update Seals information - if (IsSealSpell(m_spellProto)) - SetAuraState(AURA_STATE_JUDGEMENT); - - // Conflagrate aura state on Immolate and Shadowflame - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && - // Immolate - ((m_spellProto->SpellFamilyFlags[0] & 4) || - // Shadowflame - (m_spellProto->SpellFamilyFlags[2] & 2))) - SetAuraState(AURA_STATE_CONFLAGRATE); - - // Faerie Fire (druid versions) - if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x400) - SetAuraState(AURA_STATE_FAERIE_FIRE); - - // Sting (hunter's pet ability) - if (m_spellProto->Category == 1133) - SetAuraState(AURA_STATE_FAERIE_FIRE); - - // Victorious - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00040000) - SetAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH); - - // Swiftmend state on Regrowth & Rejuvenation - if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x50 ) - SetAuraState(AURA_STATE_SWIFTMEND); - - // Deadly poison aura state - if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x10000) - SetAuraState(AURA_STATE_DEADLY_POISON); - - // Enrage aura state - if(m_spellProto->Dispel == DISPEL_ENRAGE) - SetAuraState(AURA_STATE_ENRAGE); - - // Bleeding aura state - if (GetAllSpellMechanicMask(m_spellProto) & 1<<MECHANIC_BLEED) - SetAuraState(AURA_STATE_BLEEDING); - - if(GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST) - { - for (uint8 i = 0;i<MAX_SPELL_EFFECTS;++i) - { - if (m_spellProto->EffectApplyAuraName[i]==SPELL_AURA_MOD_STUN - || m_spellProto->EffectApplyAuraName[i]==SPELL_AURA_MOD_ROOT) - { - SetAuraState(AURA_STATE_FROZEN); - break; - } - } - } - - m_target->ApplyModFlag(UNIT_FIELD_AURASTATE, GetAuraStateMask(), true); - HandleAuraSpecificMods(true); } @@ -1300,22 +1239,6 @@ void Aura::_RemoveAura() if (getDiminishGroup() != DIMINISHING_NONE ) m_target->ApplyDiminishingAura(getDiminishGroup(),false); - // Check needed only if aura applies aurastate - if(GetAuraStateMask()) - { - uint32 foundMask = 0; - Unit::AuraMap& Auras = m_target->GetAuras(); - // Get mask of all aurastates from remaining auras - for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) - { - foundMask|=(*i).second->GetAuraStateMask(); - } - // Remove only aurastates which were not found - foundMask = GetAuraStateMask() &~foundMask; - if (foundMask) - m_target->ApplyModFlag(UNIT_FIELD_AURASTATE, foundMask, false); - } - // since now aura cannot apply/remove it's modifiers m_isRemoved = true; // disable client server communication for removed aura diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 8b780520849..637c8054524 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -84,8 +84,6 @@ class TRINITY_DLL_SPEC Aura int8 GetStackAmount() const {return m_stackAmount;} void SetStackAmount(uint8 num, bool applied = true); bool modStackAmount(int32 num); // return true if last charge dropped - uint32 GetAuraStateMask(){return m_auraStateMask;} - void SetAuraState(uint8 num){m_auraStateMask |= 1<<(num-1);} //modifies auras' aura state (not unit!) void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } uint8 GetRemoveMode() const {return m_removeMode;} @@ -154,7 +152,6 @@ class TRINITY_DLL_SPEC Aura uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount) uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount - uint32 m_auraStateMask; AuraEffect * m_partAuras[3]; uint32 m_procDamage; // used in aura proc code diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index ae708153142..f1f43d57821 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -406,6 +406,63 @@ uint32 CalculatePowerCost(SpellEntry const * spellInfo, Unit const * caster, Spe return powerCost; } +AuraState GetSpellAuraState(SpellEntry const * spellInfo) +{ + // Seals + if (IsSealSpell(spellInfo)) + return (AURA_STATE_JUDGEMENT); + + // Conflagrate aura state on Immolate and Shadowflame + if (spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && + // Immolate + ((spellInfo->SpellFamilyFlags[0] & 4) || + // Shadowflame + (spellInfo->SpellFamilyFlags[2] & 2))) + return (AURA_STATE_CONFLAGRATE); + + // Faerie Fire (druid versions) + if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && spellInfo->SpellFamilyFlags[0] & 0x400) + return (AURA_STATE_FAERIE_FIRE); + + // Sting (hunter's pet ability) + if (spellInfo->Category == 1133) + return (AURA_STATE_FAERIE_FIRE); + + // Victorious + if (spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellFamilyFlags[1] & 0x00040000) + return (AURA_STATE_WARRIOR_VICTORY_RUSH); + + // Swiftmend state on Regrowth & Rejuvenation + if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && spellInfo->SpellFamilyFlags[0] & 0x50 ) + return (AURA_STATE_SWIFTMEND); + + // Deadly poison aura state + if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags[0] & 0x10000) + return (AURA_STATE_DEADLY_POISON); + + // Enrage aura state + if(spellInfo->Dispel == DISPEL_ENRAGE) + return (AURA_STATE_ENRAGE); + + // Bleeding aura state + if (GetAllSpellMechanicMask(spellInfo) & 1<<MECHANIC_BLEED) + return (AURA_STATE_BLEEDING); + + if(GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) + { + for (uint8 i = 0;i<MAX_SPELL_EFFECTS;++i) + { + if (spellInfo->EffectApplyAuraName[i]==SPELL_AURA_MOD_STUN + || spellInfo->EffectApplyAuraName[i]==SPELL_AURA_MOD_ROOT) + { + return (AURA_STATE_FROZEN); + break; + } + } + } + return AURA_STATE_NONE; +} + SpellSpecific GetSpellSpecific(uint32 spellId) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 2540f141b43..f1d551298f0 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -134,6 +134,7 @@ enum SpellLinkedType }; SpellSpecific GetSpellSpecific(uint32 spellId); +AuraState GetSpellAuraState(SpellEntry const * spellInfo); // Different spell properties inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f48d23bd3dd..1138da4ba28 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3883,6 +3883,17 @@ bool Unit::AddAura(Aura *Aur, bool handleEffects) // add aura, register in lists and arrays Aur->_AddAura(); + + //***************************************************** + // Update target aura state flag + //***************************************************** + if(AuraState aState = GetSpellAuraState(Aur->GetSpellProto())) + { + bool found = false; + m_auraStateAuras.insert(AuraStateAurasMap::value_type(aState, Aur)); + ModifyAuraState(aState, true); + } + m_Auras.insert(AuraMap::value_type(aurId, Aur)); if(aurSpellInfo->AuraInterruptFlags) @@ -4214,6 +4225,28 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) Aur->_RemoveAura(); + bool auraStateFound = false; + if (AuraState auraState = GetSpellAuraState(Aur->GetSpellProto())) + { + bool canBreak = false; + // Get mask of all aurastates from remaining auras + for(AuraStateAurasMap::iterator itr = m_auraStateAuras.lower_bound(auraState); itr != m_auraStateAuras.upper_bound(auraState) || !(auraStateFound && canBreak);) + { + if (itr->second == Aur) + { + m_auraStateAuras.erase(itr); + itr = m_auraStateAuras.lower_bound(auraState); + canBreak = true; + continue; + } + auraStateFound = true; + ++itr; + } + // Remove only aurastates which were not found + if (!auraStateFound) + ModifyAuraState(auraState, false); + } + // Remove totem at next update if totem looses its aura if (Aur->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem()&& ((TempSummon*)this)->GetSummonerGUID()==Aur->GetCasterGUID()) { @@ -8581,15 +8614,42 @@ void Unit::ModifyAuraState(AuraState flag, bool apply) } } +uint32 Unit::BuildAuraStateUpdateForTarget(Unit * target) const +{ + uint32 auraStates = GetUInt32Value(UNIT_FIELD_AURASTATE) &~(PER_CASTER_AURA_STATE_MASK); + for(AuraStateAurasMap::const_iterator itr = m_auraStateAuras.begin(); itr != m_auraStateAuras.end();++itr) + { + if ((1<<(itr->first-1)) & PER_CASTER_AURA_STATE_MASK) + { + if (itr->second->GetCasterGUID() == target->GetGUID()) + auraStates |= (1<<(itr->first-1)); + } + } + return auraStates; +} + bool Unit::HasAuraState(AuraState flag, SpellEntry const *spellProto, Unit * Caster) const { - if (Caster && spellProto) + if (Caster) { - AuraEffectList const& stateAuras = Caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); - for(AuraEffectList::const_iterator j = stateAuras.begin();j != stateAuras.end(); ++j) - if((*j)->isAffectedOnSpell(spellProto)) - return true; + if(spellProto) + { + AuraEffectList const& stateAuras = Caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); + for(AuraEffectList::const_iterator j = stateAuras.begin();j != stateAuras.end(); ++j) + if((*j)->isAffectedOnSpell(spellProto)) + return true; + } + // Check per caster aura state + // If aura with aurastate by caster not found return false + if ((1<<(flag-1)) & PER_CASTER_AURA_STATE_MASK) + { + for(AuraStateAurasMap::const_iterator itr = m_auraStateAuras.lower_bound(flag); itr != m_auraStateAuras.upper_bound(flag);++itr) + if (itr->second->GetCasterGUID() == Caster->GetGUID()) + return true; + return false; + } } + return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); } diff --git a/src/game/Unit.h b/src/game/Unit.h index 85f2ed154dd..5a09d0f8c0e 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1023,6 +1023,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject typedef std::set<Unit*> ControlList; typedef std::pair<uint32, uint8> spellEffectPair; typedef std::multimap<uint32, Aura*> AuraMap; + typedef std::multimap<AuraState, Aura*> AuraStateAurasMap; typedef std::list<AuraEffect *> AuraEffectList; typedef std::list<Aura *> AuraList; typedef std::list<DiminishingReturn> Diminishing; @@ -1658,6 +1659,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject uint32 CalculateDamage(WeaponAttackType attType, bool normalized); float GetAPMultiplier(WeaponAttackType attType, bool normalized); void ModifyAuraState(AuraState flag, bool apply); + uint32 BuildAuraStateUpdateForTarget(Unit * target) const; bool HasAuraState(AuraState flag, SpellEntry const *spellProto = NULL, Unit * Caster = NULL) const ; void UnsummonAllTotems(); Unit* SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo = NULL); @@ -1855,12 +1857,12 @@ class TRINITY_DLL_SPEC Unit : public WorldObject AuraList m_scAuras; // casted singlecast auras AuraList m_interruptableAuras; AuraList m_removedAuras; + AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove uint32 m_interruptMask; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; - //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem VisibleAuraMap m_visibleAuras; float m_speed_rate[MAX_MOVE_TYPE]; |