aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/Player.cpp27
-rw-r--r--src/game/Player.h1
-rw-r--r--src/game/Spell.cpp17
-rw-r--r--src/game/SpellAuras.cpp21
-rw-r--r--src/game/SpellEffects.cpp2
-rw-r--r--src/game/Unit.cpp77
-rw-r--r--src/game/Unit.h26
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;