diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Player.cpp | 27 | ||||
-rw-r--r-- | src/game/Player.h | 1 | ||||
-rw-r--r-- | src/game/Spell.cpp | 17 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 21 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 77 | ||||
-rw-r--r-- | src/game/Unit.h | 26 |
7 files changed, 109 insertions, 62 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 0119d1ee0db..dfff664b31a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16605,7 +16605,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i ModifyMoney(-(int32)totalcost); // prevent stealth flight - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_STEALTH); + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LOOT); WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); data << uint32(ERR_TAXIOK); @@ -18885,6 +18885,7 @@ bool Player::isAllowUseBattleGroundObject() { return ( //InBattleGround() && // in battleground - not need, check in other cases !IsMounted() && // not mounted + !isTotalImmunity() && // not totally immuned !HasStealthAura() && // not stealthed !HasInvisibilityAura() && // not invisible !HasAura(SPELL_RECENTLY_DROPPED_FLAG, 0) && // can't pickup @@ -18900,3 +18901,27 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const return false; } + +bool Player::isTotalImmunity() +{ + AuraList const& immune = GetAurasByType(SPELL_AURA_SCHOOL_IMMUNITY); + + for(AuraList::const_iterator itr = immune.begin(); itr != immune.end(); ++itr) + { + if (((*itr)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_ALL) !=0) // total immunity + { + return true; + } + if (((*itr)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) !=0) // physical damage immunity + { + for(AuraList::const_iterator i = immune.begin(); i != immune.end(); ++i) + { + if (((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) !=0) // magic immunity + { + return true; + } + } + } + } + return false; +} diff --git a/src/game/Player.h b/src/game/Player.h index 427f97de14a..85e5808263a 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1914,6 +1914,7 @@ class TRINITY_DLL_SPEC Player : public Unit bool GetBGAccessByLevel(uint32 bgTypeId) const; bool isAllowUseBattleGroundObject(); + bool isTotalImmunity(); /*********************************************************/ /*** OUTDOOR PVP SYSTEM ***/ diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 95f315c5c13..1a22c2a529d 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -956,14 +956,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) unit->SetStandState(PLAYER_STATE_NONE); - if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) - ((Creature*)unit)->AI()->AttackStart(m_caster); - - unit->SetInCombatWith(m_caster); - m_caster->SetInCombatWith(unit); - - if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself()) - m_caster->SetContestedPvP(attackedPlayer); + m_caster->CombatStart(unit); } } } @@ -1002,11 +995,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) return; } - //if(!IsPositiveSpell(m_spellInfo->Id)) - { - //do not remove feign death - unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_STEALTH + AURA_INTERRUPT_FLAG_DAMAGE); - } + unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL); } else { @@ -2247,7 +2236,7 @@ void Spell::cast(bool skipCheck) // skip triggered spell (item equip spell casting and other not explicit character casts/item uses) if ( !m_IsTriggeredSpell && isSpellBreakStealth(m_spellInfo) ) { - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_STEALTH); + m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST); } // who did this hack? diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 25f69aa3046..e97c2ab06ff 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3071,6 +3071,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->addUnitState(UNIT_STAT_DIED); m_target->CombatStop(); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); // prevent interrupt message if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL]) @@ -3210,11 +3211,8 @@ void Aura::HandleModStealth(bool apply, bool Real) if(Real && m_target->GetTypeId()==TYPEID_PLAYER) { // drop flag at stealth in bg - if(((Player*)m_target)->InBattleGround()) - { - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->EventPlayerDroppedFlag((Player*)m_target); - } + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); + // remove player from the objective's active player count at stealth if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) pvp->HandlePlayerActivityChanged((Player*)m_target); @@ -3298,6 +3296,8 @@ void Aura::HandleInvisibility(bool apply, bool Real) { m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) { // apply glow vision @@ -3305,11 +3305,6 @@ void Aura::HandleInvisibility(bool apply, bool Real) // remove player from the objective's active player count at invisibility if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) pvp->HandlePlayerActivityChanged((Player*)m_target); - - // 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 @@ -3816,6 +3811,9 @@ void Aura::HandleAuraModStateImmunity(bool apply, bool Real) void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) { + if(apply && m_modifier.m_miscvalue == SPELL_SCHOOL_MASK_NORMAL) + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); + m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply); if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) @@ -5376,7 +5374,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_UNATTACKABLE); + } m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply); } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index b0744d9b009..d21f9ff7525 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3479,7 +3479,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) else { // Reveal action + get attack - m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_STEALTH); + m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LOOT); if (((Creature*)unitTarget)->AI()) ((Creature*)unitTarget)->AI()->AttackStart(m_caster); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7eaf495b234..d4549352bb9 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -472,7 +472,7 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag) ++next; //sLog.outDetail("auraflag:%u flag:%u = %u",(*iter)->GetSpellProto()->AuraInterruptFlags,flag,(*iter)->GetSpellProto()->AuraInterruptFlags & flag); - if(*iter && ((*iter)->GetSpellProto()->AuraInterruptFlags & flag) == flag) + if(*iter && ((*iter)->GetSpellProto()->AuraInterruptFlags & flag)) { RemoveAurasDueToSpell((*iter)->GetId()); if (!m_interruptableAuras.empty()) @@ -488,6 +488,30 @@ bool Unit::HasAuraType(AuraType auraType) const return (!m_modAuras[auraType].empty()); } +/* Called by DealDamage for auras that have a chance to be dispelled on damage taken. */ +void Unit::RemoveSpellbyDamageTaken(uint32 damage, uint32 spell) +{ + // The chance to dispel an aura depends on the damage taken with respect to the casters level. + uint32 max_dmg = getLevel() > 8 ? 25 * getLevel() - 150 : 50; + float chance = float(damage) / max_dmg * 100.0f; + + AuraList::iterator i, next; + for(i = m_ccAuras.begin(); i != m_ccAuras.end(); i = next) + { + next = i; + ++next; + + if(*i && (!spell || (*i)->GetId() != spell) && roll_chance_f(chance)) + { + RemoveAurasDueToSpell((*i)->GetId()); + if (!m_ccAuras.empty()) + next = m_ccAuras.begin(); + else + return; + } + } +} + uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss) { if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) @@ -509,8 +533,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa // remove affects from attacker at any non-DoT damage (including 0 damage) if( damagetype != DOT) { - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_STEALTH); - if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNNED)) pVictim->SetStandState(PLAYER_STATE_NONE); } @@ -888,7 +910,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa } // TODO: Store auras by interrupt flag to speed this up. - AuraMap& vAuras = pVictim->GetAuras(); + /*AuraMap& vAuras = pVictim->GetAuras(); for (AuraMap::iterator i = vAuras.begin(), next; i != vAuras.end(); i = next) { const SpellEntry *se = i->second->GetSpellProto(); @@ -908,17 +930,9 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa next = vAuras.begin(); } } - else if ( (se->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) && (!spellProto || se->Id != spellProto->Id) ) - { - uint32 max_dmg = pVictim->getLevel() > 8 ? 25 * pVictim->getLevel() - 150 : 50; - float chance = float(damage) / max_dmg * 100.0f; - if (roll_chance_f(chance)) - { - pVictim->RemoveAurasDueToSpell(i->second->GetId()); - next = vAuras.begin(); - } - } - } + else */ + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DAMAGE); + pVictim->RemoveSpellbyDamageTaken(damage, spellProto ? spellProto->Id : 0); if (damagetype != NODAMAGE && damage && pVictim->GetTypeId() == TYPEID_PLAYER) { @@ -2192,14 +2206,7 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex if(IsNonMeleeSpellCasted(false)) return; - if(!pVictim->isInCombat() && pVictim->GetTypeId() != TYPEID_PLAYER && ((Creature*)pVictim)->AI()) - ((Creature*)pVictim)->AI()->AttackStart(this); - - SetInCombatWith(pVictim); - pVictim->SetInCombatWith(this); - - if(Player* attackedPlayer = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself()) - SetContestedPvP(attackedPlayer); + CombatStart(pVictim); uint32 hitInfo; if (attType == BASE_ATTACK) @@ -3789,6 +3796,11 @@ bool Unit::AddAura(Aura *Aur) m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur); if(Aur->GetSpellProto()->AuraInterruptFlags) m_interruptableAuras.push_back(Aur); + if(Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) + { + m_ccAuras.push_back(Aur); + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC); + } } Aur->ApplyModifier(true,true); @@ -4152,6 +4164,8 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second); if((*i).second->GetSpellProto()->AuraInterruptFlags) m_interruptableAuras.remove((*i).second); + if((*i).second->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) + m_ccAuras.remove((*i).second); } // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) @@ -8398,7 +8412,7 @@ void Unit::Mount(uint32 mount) if(!mount) return; - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING); + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT); SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, mount); @@ -8468,6 +8482,21 @@ void Unit::SetInCombatWith(Unit* enemy) SetInCombatState(false); } +void Unit::CombatStart(Unit* target) +{ + if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER && ((Creature*)target)->AI()) + ((Creature*)target)->AI()->AttackStart(this); + + SetInCombatWith(target); + target->SetInCombatWith(this); + + if(Player* attackedPlayer = target->GetCharmerOrOwnerPlayerOrPlayerItself()) + SetContestedPvP(attackedPlayer); + + if(!isInCombat()) // remove this? + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ATTACK); +} + void Unit::SetInCombatState(bool PvP) { // only alive units can be in combat diff --git a/src/game/Unit.h b/src/game/Unit.h index 61dcaf0d1cd..f0b74e5df6c 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -57,30 +57,29 @@ enum SpellChannelInterruptFlags enum SpellAuraInterruptFlags { - AURA_INTERRUPT_FLAG_UNK0 = 0x00000001, // 0 removed when getting hit by a negative spell? + AURA_INTERRUPT_FLAG_HITBYSPELL = 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_CC = 0x00000004, // 2 crowd control 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_JUMP = 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_STEALTH = 0x00003C00, + AURA_INTERRUPT_FLAG_LOOT = 0x00000400, // 10 + AURA_INTERRUPT_FLAG_MOUNT = 0x00000800, // 11 removed by mounting + AURA_INTERRUPT_FLAG_ATTACK = 0x00001000, // 12 removed by attacking + AURA_INTERRUPT_FLAG_CAST = 0x00002000, // 13 ??? AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 - AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? + AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform? AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 - AURA_INTERRUPT_FLAG_MOUNTING = 0x00020000, // 17 removed by mounting + AURA_INTERRUPT_FLAG_UNK17 = 0x00020000, // 17 misdirect, aspect, swim speed 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_UNK20 = 0x00100000, // 20 + AURA_INTERRUPT_FLAG_UNATTACKABLE = 0x00100000, // 20 invulnerable or stealth AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 - AURA_INTERRUPT_FLAG_UNK22 = 0x00400000, // 22 + AURA_INTERRUPT_FLAG_TELEPORTED = 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 }; @@ -844,6 +843,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void Unmount(); uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } + void RemoveSpellbyDamageTaken(uint32 damage, uint32 spell); uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss); void DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit = false, bool isTriggeredSpell = false); void DoAttackDamage(Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); @@ -902,6 +902,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool isInFlight() const { return hasUnitState(UNIT_STAT_IN_FLIGHT); } bool isInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); } + void CombatStart(Unit* target); void SetInCombatState(bool PvP); void SetInCombatWith(Unit* enemy); void ClearInCombat(); @@ -1334,6 +1335,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject AuraList m_modAuras[TOTAL_AURAS]; AuraList m_interruptableAuras; + AuraList m_ccAuras; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; |