diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index dd04a7857..fad0a40f4 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1176,7 +1176,7 @@ void BattleGroundMgr::Update(uint32 diff) // skip updating battleground template if( itr != m_BattleGrounds[i].end() ) ++itr; - for(itr = m_BattleGrounds[i].begin(); itr != m_BattleGrounds[i].end(); itr = next) + for(; itr != m_BattleGrounds[i].end(); itr = next) { next = itr; ++next; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 61587aab6..190d62219 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18794,6 +18794,7 @@ void Player::SummonIfPossible(bool agree) } // drop flag at summon + // this code can be reached only when GM is summoning player who carries flag, because player should be immune to summoning spells when he carries flag if(BattleGround *bg = GetBattleGround()) bg->EventPlayerDroppedFlag(this); @@ -19440,6 +19441,7 @@ bool Player::CanUseBattleGroundObject() return ( //InBattleGround() && // in battleground - not need, check in other cases //!IsMounted() && - not correct, player is dismounted when he clicks on flag //i'm not sure if these two are correct, because invisible players should get visible when they click on flag + !isTotalImmune() && // not totally immune !HasStealthAura() && // not stealthed !HasInvisibilityAura() && // not invisible !HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup @@ -19607,6 +19609,20 @@ void Player::ExitVehicle(Vehicle *vehicle) CastSpell(this, 45472, true); // Parachute } +bool Player::isTotalImmune() +{ + AuraList const& immune = GetAurasByType(SPELL_AURA_SCHOOL_IMMUNITY); + + uint32 immuneMask = 0; + for(AuraList::const_iterator itr = immune.begin(); itr != immune.end(); ++itr) + { + immuneMask |= (*itr)->GetModifier()->m_miscvalue; + if( immuneMask & SPELL_SCHOOL_MASK_ALL ) // total immunity + return true; + } + return false; +} + bool Player::HasTitle(uint32 bitIndex) { if (bitIndex > 128) diff --git a/src/game/Player.h b/src/game/Player.h index 1004b5b5d..4f0b1252a 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1912,6 +1912,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const; bool CanUseBattleGroundObject(); + bool isTotalImmune(); bool CanCaptureTowerPoint(); /*********************************************************/ diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 9406c6ba0..fc917d5e2 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -296,7 +296,7 @@ enum ItemQualities #define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet #define SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT 0x00080000 // 19 does not necessarly need shapeshift #define SPELL_ATTR_EX2_UNK20 0x00100000 // 20 -#define SPELL_ATTR_EX2_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD 0x00200000 // 21 for ice blocks, pala immunity buffs, priest absorb shields, but used also for other spells -> not sure! #define SPELL_ATTR_EX2_UNK22 0x00400000 // 22 #define SPELL_ATTR_EX2_UNK23 0x00800000 // 23 Only mage Arcane Concentration have this flag #define SPELL_ATTR_EX2_UNK24 0x01000000 // 24 diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 94a218a5e..b43667db5 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3306,6 +3306,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->addUnitState(UNIT_STAT_DIED); m_target->CombatStop(); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); // prevent interrupt message if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL]) @@ -3488,9 +3489,7 @@ void Aura::HandleModStealth(bool apply, bool Real) if(apply) { // drop flag at stealth in bg - if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround()) - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->EventPlayerDroppedFlag((Player*)m_target); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); // only at real aura add if(Real) @@ -3555,15 +3554,13 @@ void Aura::HandleInvisibility(bool apply, bool Real) { m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) { // apply glow vision m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - // drop flag at invisible in bg - if(((Player*)m_target)->InBattleGround()) - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->EventPlayerDroppedFlag((Player*)m_target); } // apply only if not in GM invisibility and not stealth @@ -4010,44 +4007,15 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) } } +//this method is called whenever we add / remove aura which gives m_target some imunity to some spell effect void Aura::HandleAuraModEffectImmunity(bool apply, bool Real) { - if(!apply) + // when removing flag aura, handle flag drop + if( !apply && m_target->GetTypeId() == TYPEID_PLAYER + && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION) ) { - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(((Player*)m_target)->InBattleGround()) - { - BattleGround *bg = ((Player*)m_target)->GetBattleGround(); - if(bg) - { - switch(bg->GetTypeID()) - { - case BATTLEGROUND_AV: - { - break; - } - case BATTLEGROUND_WS: - { - // Warsong Flag, horde // Silverwing Flag, alliance - if(GetId() == 23333 || GetId() == 23335) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - break; - } - case BATTLEGROUND_AB: - { - break; - } - case BATTLEGROUND_EY: - { - if(GetId() == 34976) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - break; - } - } - } - } - } + if( BattleGround *bg = ((Player*)m_target)->GetBattleGround() ) + bg->EventPlayerDroppedFlag(((Player*)m_target)); } m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply); @@ -4077,28 +4045,33 @@ void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) { m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply); - if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + // remove all flag auras (they are positive, but they must be removed when you are immune) + if( this->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY + && this->GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD ) + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + + // TODO: optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else + if( Real && apply + && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY + && IsPositiveSpell(GetId()) ) //Only positive immunity removes auras { - if(IsPositiveSpell(GetId())) //Only positive immunity removes auras + uint32 school_mask = m_modifier.m_miscvalue; + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) { - uint32 school_mask = m_modifier.m_miscvalue; - Unit::AuraMap& Auras = m_target->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + next = iter; + ++next; + SpellEntry const *spell = iter->second->GetSpellProto(); + if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask + && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability + && !iter->second->IsPositive() //Don't remove positive spells + && spell->Id != GetId() ) //Don't remove self { - next = iter; - ++next; - SpellEntry const *spell = iter->second->GetSpellProto(); - if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask - && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability - && !iter->second->IsPositive() //Don't remove positive spells - && spell->Id != GetId() ) //Don't remove self - { - m_target->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } + m_target->RemoveAurasDueToSpell(spell->Id); + if(Auras.empty()) + break; + else + next = Auras.begin(); } } } @@ -5559,8 +5532,10 @@ void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) void Aura::HandleModUnattackable( bool Apply, bool Real ) { if(Real && Apply) + { m_target->CombatStop(); - + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + } m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply); } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 51bd8e48e..0e36af6d4 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2369,6 +2369,8 @@ void Spell::EffectPowerDrain(uint32 i) void Spell::EffectSendEvent(uint32 EffectIndex) { + /* we do not drop a flag by sendevent system, OBSOLETE CODE: + this code caused crashes if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround()) { BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); @@ -2377,25 +2379,22 @@ void Spell::EffectSendEvent(uint32 EffectIndex) switch(m_spellInfo->Id) { case 23333: // Pickup Horde Flag - /*do not uncomment . + /*do not uncomment if(bg->GetTypeID()==BATTLEGROUND_WS) bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Send Event Horde Flag Picked Up"); break; - /* not used : case 23334: // Drop Horde Flag if(bg->GetTypeID()==BATTLEGROUND_WS) bg->EventPlayerDroppedFlag((Player*)m_caster); sLog.outDebug("Drop Horde Flag"); break; - */ case 23335: // Pickup Alliance Flag - /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion + /*do not uncomment - it will cause crash, because of null targetobject! if(bg->GetTypeID()==BATTLEGROUND_WS) bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Send Event Alliance Flag Picked Up"); break; - /* not used : case 23336: // Drop Alliance Flag if(bg->GetTypeID()==BATTLEGROUND_WS) bg->EventPlayerDroppedFlag((Player*)m_caster); @@ -2410,19 +2409,17 @@ void Spell::EffectSendEvent(uint32 EffectIndex) if(bg->GetTypeID()==BATTLEGROUND_WS) bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); sLog.outDebug("Horde Flag Returned"); - break;*/ + break; case 34976: - /* if(bg->GetTypeID()==BATTLEGROUND_EY) bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); - */ break; default: sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id); break; } } - } + }*/ sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id); sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject); } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 43db31e65..875459fc0 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -298,10 +298,6 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex) switch(spellId) { - case 23333: // BG spell - case 23335: // BG spell - case 34976: // BG spell - return true; case 28441: // not positive dummy spell case 37675: // Chaos Blast return false; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 479fd9ee9..39ca7531a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8245,6 +8245,9 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) return true; } + //TODO add spellEffect immunity checks!, player with flag in bg is imune to imunity buffs from other friendly players! + //SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_EFFECT]; + SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL]; for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr) if(itr->type == spellInfo->Dispel) diff --git a/src/game/Unit.h b/src/game/Unit.h index 92116fb69..3b6013701 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -55,31 +55,31 @@ enum SpellChannelInterruptFlags enum SpellAuraInterruptFlags { - AURA_INTERRUPT_FLAG_UNK0 = 0x00000001, // 0 removed when getting hit by a negative spell? - AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage - AURA_INTERRUPT_FLAG_UNK2 = 0x00000004, // 2 - AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement - AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning - AURA_INTERRUPT_FLAG_ENTER_COMBAT = 0x00000020, // 5 removed by entering combat - AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting - AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water - AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water - AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing - AURA_INTERRUPT_FLAG_UNK10 = 0x00000400, // 10 - AURA_INTERRUPT_FLAG_UNK11 = 0x00000800, // 11 - AURA_INTERRUPT_FLAG_UNK12 = 0x00001000, // 12 removed by attack? - AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13 - AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 - AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? - AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 - AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting - AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up - AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported - AURA_INTERRUPT_FLAG_IMMUNE_OR_STEALTH = 0x00100000, // 20 removed when player on himself casts immunity spell or vanish? - AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 - AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22 - AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat - AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000 // 24 removed by any direct damage + AURA_INTERRUPT_FLAG_UNK0 = 0x00000001, // 0 removed when getting hit by a negative spell? + AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage + AURA_INTERRUPT_FLAG_UNK2 = 0x00000004, // 2 + AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement + AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning + AURA_INTERRUPT_FLAG_ENTER_COMBAT = 0x00000020, // 5 removed by entering combat + AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting + AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water + AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water + AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing + AURA_INTERRUPT_FLAG_UNK10 = 0x00000400, // 10 + AURA_INTERRUPT_FLAG_UNK11 = 0x00000800, // 11 + AURA_INTERRUPT_FLAG_UNK12 = 0x00001000, // 12 removed by attack? + AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13 + AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 + AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? + AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 + AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting + AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up + AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported + AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to loose selection on you + AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 + AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22 + AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat + AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000 // 24 removed by any direct damage }; enum SpellModOp diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1b243e457..2be920294 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7522" + #define REVISION_NR "7523" #endif // __REVISION_NR_H__