diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/ArenaTeam.cpp | 4 | ||||
-rw-r--r-- | src/game/ArenaTeamHandler.cpp | 4 | ||||
-rw-r--r-- | src/game/SharedDefines.h | 8 | ||||
-rw-r--r-- | src/game/Spell.cpp | 34 | ||||
-rw-r--r-- | src/game/Unit.cpp | 122 | ||||
-rw-r--r-- | src/game/Unit.h | 14 |
6 files changed, 87 insertions, 99 deletions
diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 8d89a841a2f..4d9f3bed1a1 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -10,12 +10,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "WorldPacket.h" diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp index 78a90456797..b5f8e69c918 100644 --- a/src/game/ArenaTeamHandler.cpp +++ b/src/game/ArenaTeamHandler.cpp @@ -10,12 +10,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "WorldSession.h" diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 072c6947cdf..56a9a14bcc7 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -220,11 +220,11 @@ enum ItemQualities #define SPELL_ATTR_LEVEL_DAMAGE_CALCULATION 0x00080000 // 19 spelldamage depends on caster level #define SPELL_ATTR_STOP_ATTACK_TARGET 0x00100000 // 20 Stop attack after use this spell (and not begin attack if use) #define SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK 0x00200000 // 21 Cannot be dodged/parried/blocked -#define SPELL_ATTR_UNK22 0x00400000 // 22 +#define SPELL_ATTR_UNK22 0x00400000 // 22 shoot spells #define SPELL_ATTR_UNK23 0x00800000 // 23 castable while dead? #define SPELL_ATTR_CASTABLE_WHILE_MOUNTED 0x01000000 // 24 castable while mounted #define SPELL_ATTR_DISABLED_WHILE_ACTIVE 0x02000000 // 25 Activate and start cooldown after aura fade or remove summoned creature or go -#define SPELL_ATTR_UNK26 0x04000000 // 26 +#define SPELL_ATTR_UNK26 0x04000000 // 26 Aura ignore immune? #define SPELL_ATTR_CASTABLE_WHILE_SITTING 0x08000000 // 27 castable while sitting #define SPELL_ATTR_CANT_USED_IN_COMBAT 0x10000000 // 28 Cannot be used in combat #define SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY 0x20000000 // 29 unaffected by invulnerability (hmm possible not...) @@ -266,7 +266,7 @@ enum ItemQualities #define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 #define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 -#define SPELL_ATTR_EX2_UNK2 0x00000004 // 2 +#define SPELL_ATTR_EX2_UNK2 0x00000004 // 2 boss spells? #define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 #define SPELL_ATTR_EX2_UNK4 0x00000010 // 4 #define SPELL_ATTR_EX2_UNK5 0x00000020 // 5 @@ -305,7 +305,7 @@ enum ItemQualities #define SPELL_ATTR_EX3_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX3_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX3_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX3_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX3_PLAYERS_ONLY 0x00000100 // 8 Player only? #define SPELL_ATTR_EX3_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required #define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 8d5eee36d01..d7c68ed344a 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -954,9 +954,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) { if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) { - if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) - unit->SetStandState(PLAYER_STATE_NONE); - m_caster->CombatStart(unit); } } @@ -1282,7 +1279,7 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier); cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); } - if(!(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_PLAYERS_ONLY)) + if(!(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY)) { TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier); cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)); @@ -2297,7 +2294,7 @@ void Spell::cast(bool skipCheck) } // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells - if (m_spellInfo->speed > 0.0f) + if (m_spellInfo->speed > 0.0f && !IsChanneledSpell(m_spellInfo)) { // Remove used for cast item if need (it can be already NULL after TakeReagents call @@ -2324,6 +2321,7 @@ void Spell::handle_immediate() if(IsChanneledSpell(m_spellInfo)) { m_spellState = SPELL_STATE_CASTING; + m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); SendChannelStart(GetSpellDuration(m_spellInfo)); } @@ -2567,10 +2565,11 @@ void Spell::update(uint32 difftime) (m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING))) { // always cancel for channeled spells - if( m_spellState == SPELL_STATE_CASTING ) - cancel(); + //if( m_spellState == SPELL_STATE_CASTING ) + // cancel(); // don't cancel for melee, autorepeat, triggered and instant spells - else if(!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)) + //else + if(!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)) cancel(); } @@ -2602,10 +2601,6 @@ void Spell::update(uint32 difftime) // check for incapacitating player states if( m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_CONFUSED)) cancel(); - - // check if player has turned if flag is set - if( m_spellInfo->ChannelInterruptFlags & CHANNEL_FLAG_TURNING && m_castOrientation != m_caster->GetOrientation() ) - cancel(); } // check if there are alive targets left @@ -2669,6 +2664,9 @@ void Spell::finish(bool ok) if(!m_caster) return; + if(IsChanneledSpell(m_spellInfo)) + m_caster->UpdateInterruptMask(); + if(m_spellState == SPELL_STATE_FINISHED) return; @@ -4761,17 +4759,17 @@ uint8 Spell::CheckItems() return uint8(0); } -void Spell::Delayed() +void Spell::Delayed() // only called in DealDamage() { - if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) + if(!m_caster)// || m_caster->GetTypeId() != TYPEID_PLAYER) return; - if (m_spellState == SPELL_STATE_DELAYED) - return; // spell is active and can't be time-backed + //if (m_spellState == SPELL_STATE_DELAYED) + // return; // spell is active and can't be time-backed // spells not loosing casting time ( slam, dynamites, bombs.. ) - if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)) - return; + //if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)) + // return; //check resist chance int32 resistChance = 100; //must be initialized to 100 for percent modifiers diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b31ec79ec49..1c793cc71bf 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -181,6 +181,7 @@ Unit::Unit() m_Visibility = VISIBILITY_ON; + m_interruptMask = 0; m_detectInvisibilityMask = 0; m_invisibilityMask = 0; m_transform = 0; @@ -465,6 +466,10 @@ void Unit::RemoveSpellsCausingAura(AuraType auraType) void Unit::RemoveAurasWithInterruptFlags(uint32 flag) { + if(!(m_interruptMask & flag)) + return; + + // interrupt auras AuraList::iterator iter, next; for (iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); iter = next) { @@ -478,9 +483,27 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag) if (!m_interruptableAuras.empty()) next = m_interruptableAuras.begin(); else - return; + break; } } + + // interrupt channeled spell + if(Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + if(spell->getState() == SPELL_STATE_CASTING && (spell->m_spellInfo->AuraInterruptFlags & flag)) + InterruptNonMeleeSpells(false); +} + +void Unit::UpdateInterruptMask() +{ + m_interruptMask = 0; + for(AuraList::iterator i = m_interruptableAuras.begin(); i != m_interruptableAuras.end(); ++i) + { + if(*i) + m_interruptMask |= (*i)->GetSpellProto()->AuraInterruptFlags; + } + if(Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + if(spell->getState() == SPELL_STATE_CASTING) + m_interruptMask |= spell->m_spellInfo->AuraInterruptFlags; } bool Unit::HasAuraType(AuraType auraType) const @@ -526,22 +549,11 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa return 0; } - // remove affects from victim (including from 0 damage and DoTs) - //if(pVictim != this) - // pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - - // remove affects from attacker at any non-DoT damage (including 0 damage) - if( damagetype != DOT) - { - if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNNED)) - pVictim->SetStandState(PLAYER_STATE_NONE); - } - //Script Event damage taken if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() ) ((Creature *)pVictim)->AI()->DamageTaken(this, damage); - if(!damage) + if(!damage) //when will zero damage? need interrupt aura? { // Rage from physical damage received . if(cleanDamage && cleanDamage->damage && (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) && pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE)) @@ -868,10 +880,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa } } - // polymorphed and other negative transformed cases - if(pVictim->getTransForm() && pVictim->hasUnitState(UNIT_STAT_CONFUSED)) - pVictim->RemoveAurasDueToSpell(pVictim->getTransForm()); - if(damagetype == DIRECT_DAMAGE|| damagetype == SPELL_DIRECT_DAMAGE) pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE); @@ -909,68 +917,37 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa } } - // TODO: Store auras by interrupt flag to speed this up. - /*AuraMap& vAuras = pVictim->GetAuras(); - for (AuraMap::iterator i = vAuras.begin(), next; i != vAuras.end(); i = next) + if (damagetype != NODAMAGE && damage)// && pVictim->GetTypeId() == TYPEID_PLAYER) { - const SpellEntry *se = i->second->GetSpellProto(); - next = i; ++next; - if( se->AuraInterruptFlags & AURA_INTERRUPT_FLAG_DAMAGE ) - { - bool remove = true; - if (se->procFlags & (1<<3)) - { - if (!roll_chance_i(se->procChance)) - remove = false; - } - if (remove) - { - pVictim->RemoveAurasDueToSpell(i->second->GetId()); - // FIXME: this may cause the auras with proc chance to be rerolled several times - next = vAuras.begin(); - } - } - else */ - pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DAMAGE); - pVictim->RemoveSpellbyDamageTaken(damage, spellProto ? spellProto->Id : 0); + //if (se->procFlags & (1<<3)) + pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DAMAGE); + pVictim->RemoveSpellbyDamageTaken(damage, spellProto ? spellProto->Id : 0); - if (damagetype != NODAMAGE && damage && pVictim->GetTypeId() == TYPEID_PLAYER) - { - if( damagetype != DOT ) + if(pVictim != this && pVictim->GetTypeId() == TYPEID_PLAYER) // does not support creature push_back { - for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + if(damagetype != DOT) { - // skip channeled spell (processed differently below) - if (i == CURRENT_CHANNELED_SPELL) - continue; - - if(Spell* spell = pVictim->m_currentSpells[i]) + if(Spell* spell = pVictim->m_currentSpells[CURRENT_GENERIC_SPELL]) + { if(spell->getState() == SPELL_STATE_PREPARING) - spell->Delayed(); + { + uint32 interruptFlags = spell->m_spellInfo->InterruptFlags; + if(interruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE) + pVictim->InterruptNonMeleeSpells(false); + else if(interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK) + spell->Delayed(); + } + } } - } - if(Spell* spell = pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - if (spell->getState() == SPELL_STATE_CASTING) + if(Spell* spell = pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL]) { - uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags; - if( channelInterruptFlags & CHANNEL_FLAG_DELAY ) + if(spell->getState() == SPELL_STATE_CASTING) { - if(pVictim!=this) //don't shorten the duration of channeling if you damage yourself + uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags; + if( channelInterruptFlags & CHANNEL_FLAG_DELAY ) spell->DelayedChannel(); } - else if( (channelInterruptFlags & (CHANNEL_FLAG_DAMAGE | CHANNEL_FLAG_DAMAGE2)) ) - { - sLog.outDetail("Spell %u canceled at damage!",spell->m_spellInfo->Id); - pVictim->InterruptSpell(CURRENT_CHANNELED_SPELL); - } - } - else if (spell->getState() == SPELL_STATE_DELAYED) - // break channeled spell in delayed state on damage - { - sLog.outDetail("Spell %u canceled at damage!",spell->m_spellInfo->Id); - pVictim->InterruptSpell(CURRENT_CHANNELED_SPELL); } } } @@ -3795,7 +3772,10 @@ bool Unit::AddAura(Aura *Aur) { m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur); if(Aur->GetSpellProto()->AuraInterruptFlags) + { m_interruptableAuras.push_back(Aur); + AddInterruptMask(Aur->GetSpellProto()->AuraInterruptFlags); + } if(Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) { m_ccAuras.push_back(Aur); @@ -4163,7 +4143,10 @@ 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); + UpdateInterruptMask(); + } if((*i).second->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE) m_ccAuras.remove((*i).second); } @@ -8484,6 +8467,9 @@ void Unit::SetInCombatWith(Unit* enemy) void Unit::CombatStart(Unit* target) { + if(!target->IsStandState() && !target->hasUnitState(UNIT_STAT_STUNNED)) + target->SetStandState(PLAYER_STATE_NONE); + if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER && ((Creature*)target)->AI()) ((Creature*)target)->AI()->AttackStart(this); diff --git a/src/game/Unit.h b/src/game/Unit.h index 83c005b1163..94951593f2b 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -39,11 +39,11 @@ enum SpellInterruptFlags { - SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, - SPELL_INTERRUPT_FLAG_DAMAGE = 0x02, - SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, - SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, - //SPELL_INTERRUPT_FLAG_TURNING = 0x10 // not turning - maybe _complete_ interrupt on direct damage? + SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant? + SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back + SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt + SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no + SPELL_INTERRUPT_FLAG_DAMAGE = 0x10 // _complete_ interrupt on direct damage? }; enum SpellChannelInterruptFlags @@ -1188,6 +1188,9 @@ class TRINITY_DLL_SPEC Unit : public WorldObject int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; Aura* GetDummyAura(uint32 spell_id) const; + uint32 GetInterruptMask() const { return m_interruptMask; } + void AddInterruptMask(uint32 mask) { m_interruptMask |= mask; } + void UpdateInterruptMask(); uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } void SetDisplayId(uint32 modelId); @@ -1334,6 +1337,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject uint32 m_removedAuras; AuraList m_modAuras[TOTAL_AURAS]; + uint32 m_interruptMask; AuraList m_interruptableAuras; AuraList m_ccAuras; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; |