diff options
author | QAston <none@none> | 2010-08-30 17:32:51 +0200 |
---|---|---|
committer | QAston <none@none> | 2010-08-30 17:32:51 +0200 |
commit | a8de57559bb98dafb1685ce5dda2392d26844f06 (patch) | |
tree | 3b30787b25833d596733953364ecc26d59aab87e /src | |
parent | 405f312918136510fde921403ffffa315bdbcb4b (diff) |
*Allow channeled spells to be casted on dead target
*Define relted spell attributes
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Conditions/ConditionMgr.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 81 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 42 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 3 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.h | 15 |
9 files changed, 129 insertions, 29 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index a3479bf417f..8763e61d95a 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -823,6 +823,11 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) "TARGET_GAMEOBJECT_AREA_SRC(51), TARGET_GAMEOBJECT_AREA_DST(52)", cond->mSourceEntry); return false; } + if ((cond->mConditionValue1 == SPELL_TARGET_TYPE_DEAD) && !IsAllowingDeadTargetSpell(spellProto)) + { + sLog.outErrorDb("SourceEntry %u in `condition` table does have SPELL_TARGET_TYPE_DEAD specified but spell does not have SPELL_ATTR_EX2_ALLOW_DEAD_TARGET", cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 322899f8b74..7a0e74e6894 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -16388,6 +16388,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // Do now before stats re-calculation cleanup for ghost state unexpected auras if (!isAlive()) RemoveAllAurasOnDeath(); + else + RemoveAllAurasRequiringDeadTarget(); //apply all stat bonuses from items and auras SetCanModifyStats(true); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 74f5b5f469a..16c7b739260 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12504,9 +12504,10 @@ void Unit::setDeathState(DeathState s) if (oldDeathState != ALIVE && s == ALIVE) { - //_ApplyAllAuraMods(); // Reset display id on resurection - needed by corpse explosion to cleanup after display change - SetDisplayId(GetNativeDisplayId()); + // TODO: fix this + if (!HasAuraType(SPELL_AURA_TRANSFORM)) + SetDisplayId(GetNativeDisplayId()); } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index b5af7a62253..ed66354336b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1609,6 +1609,7 @@ class Unit : public WorldObject void RemoveAllAuras(); void RemoveArenaAuras(bool onleave = false); void RemoveAllAurasOnDeath(); + void RemoveAllAurasRequiringDeadTarget(); void DelayOwnedAuras(uint32 spellId, uint64 caster, int32 delaytime); void _RemoveAllAuraStatMods(); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 7b0798d4b14..dc97eeb1e4a 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -323,7 +323,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { #define SPELL_ATTR_EX_ENABLE_AT_DODGE 0x40000000 // 30 Overpower, Wolverine Bite #define SPELL_ATTR_EX_UNK31 0x80000000 // 31 -#define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 +#define SPELL_ATTR_EX2_ALLOW_DEAD_TARGET 0x00000001 // 0 #define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 ? many triggered spells have this flag #define SPELL_ATTR_EX2_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected #define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 @@ -368,7 +368,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { #define SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2 0x00000200 // 9 triggered from effect? #define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required #define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground -#define SPELL_ATTR_EX3_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX3_REQUIRE_DEAD_TARGET 0x00001000 // 12 #define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag #define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 228b4dcadad..aa6e3ee8c7c 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1244,15 +1244,6 @@ void AuraEffect::SendTickImmune(Unit * target, Unit *caster) const void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const { - if (!target->isAlive()) - return; - - if (target->hasUnitState(UNIT_STAT_ISOLATED)) - { - SendTickImmune(target, caster); - return; - } - bool prevented = GetBase()->CallScriptEffectPeriodicHandlers(const_cast<AuraEffect const *>(this), GetBase()->GetApplicationOfTarget(target->GetGUID())); if (prevented) return; @@ -1265,6 +1256,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (!caster) break; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + // Consecrate ticks can miss and will not show up in the combat log if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE) @@ -1405,6 +1405,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (!caster->isAlive()) return; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE) return; @@ -1485,6 +1494,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (!caster || !caster->GetHealth()) break; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + uint32 damage = GetAmount(); // do not kill health donator if (caster->GetHealth() < damage) @@ -1509,6 +1527,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (!caster) break; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + // heal for caster damage (must be alive) if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL && !caster->isAlive()) break; @@ -1607,6 +1634,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (GetMiscValue() < 0 || GetMiscValue() >= int8(MAX_POWERS)) break; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + Powers power = Powers(GetMiscValue()); // power type might have changed between aura applying and tick (druid's shapeshift) @@ -1711,6 +1747,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (GetMiscValue() < 0) return; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + Powers power; if (GetMiscValue() == POWER_ALL) power = target->getPowerType(); @@ -1742,6 +1787,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (m_amount < 0 || GetMiscValue() >= int8(MAX_POWERS)) return; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + Powers power = Powers(GetMiscValue()); if (target->GetMaxPower(power) == 0) @@ -1769,6 +1823,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const if (!caster) return; + if (!target->isAlive()) + return; + + if (target->hasUnitState(UNIT_STAT_ISOLATED)) + { + SendTickImmune(target, caster); + return; + } + // Check for immune (not use charges) if (target->IsImmunedToDamage(GetSpellProto())) { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index af9ad32490f..7de3b7a38d1 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -507,7 +507,7 @@ m_caster(Caster), m_spellValue(new SpellValue(m_spellInfo)) m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before. m_timer = 0; // will set to castime in prepare - m_needAliveTargetMask = 0; + m_channelTargetEffectMask = 0; // determine reflection m_canReflect = false; @@ -789,7 +789,7 @@ void Spell::SelectSpellTargets() { if (ihit->effectMask & mask) { - m_needAliveTargetMask |= mask; + m_channelTargetEffectMask |= mask; break; } } @@ -1682,19 +1682,19 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo *target) bool Spell::UpdateChanneledTargetList() { // Not need check return true - if (m_needAliveTargetMask == 0) + if (m_channelTargetEffectMask == 0) return true; - uint8 needAliveTargetMask = m_needAliveTargetMask; - uint8 needAuraMask = 0; + uint8 channelTargetEffectMask = m_channelTargetEffectMask; + uint8 channelAuraMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA) - needAuraMask |= 1<<i; + channelAuraMask |= 1<<i; - needAuraMask &= needAliveTargetMask; + channelAuraMask &= channelTargetEffectMask; float range = 0; - if (needAuraMask) + if (channelAuraMask) { range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); if (Player * modOwner = m_caster->GetSpellModOwner()) @@ -1703,13 +1703,16 @@ bool Spell::UpdateChanneledTargetList() for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { - if (ihit->missCondition == SPELL_MISS_NONE && (needAliveTargetMask & ihit->effectMask)) + if (ihit->missCondition == SPELL_MISS_NONE && (channelTargetEffectMask & ihit->effectMask)) { Unit *unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); - if (unit && unit->isAlive()) + if (!unit) + continue; + + if (IsValidDeadOrAliveTarget(unit)) { - if (needAuraMask & ihit->effectMask) + if (channelAuraMask & ihit->effectMask) { if (AuraApplication * aurApp = unit->GetAuraApplication(m_spellInfo->Id, m_originalCasterGUID)) { @@ -1724,13 +1727,13 @@ bool Spell::UpdateChanneledTargetList() continue; } - needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target + channelTargetEffectMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target } } } // is all effects from m_needAliveTargetMask have alive targets - return needAliveTargetMask == 0; + return channelTargetEffectMask == 0; } // Helper for Chain Healing @@ -4092,7 +4095,7 @@ void Spell::WriteSpellGoTargets(WorldPacket * data) if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits { *data << uint64(ihit->targetGUID); - m_needAliveTargetMask |=ihit->effectMask; + m_channelTargetEffectMask |=ihit->effectMask; } } @@ -4112,7 +4115,7 @@ void Spell::WriteSpellGoTargets(WorldPacket * data) } // Reset m_needAliveTargetMask for non channeled spell if (!IsChanneledSpell(m_spellInfo)) - m_needAliveTargetMask = 0; + m_channelTargetEffectMask = 0; } void Spell::SendLogExecute() @@ -6915,6 +6918,15 @@ bool Spell::IsValidSingleTargetSpell(Unit const* target) const return true; } +bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const +{ + if (target->isAlive()) + return !IsRequiringDeadTargetSpell(m_spellInfo); + if (IsAllowingDeadTargetSpell(m_spellInfo)) + return true; + return false; +} + void Spell::CalculateDamageDoneForAllTargets() { float multiplier[MAX_SPELL_EFFECTS]; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 1ac87cfb789..6d971a3984b 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -631,7 +631,7 @@ class Spell int32 damage; }; std::list<TargetInfo> m_UniqueTargetInfo; - uint8 m_needAliveTargetMask; // Mask req. alive targets + uint8 m_channelTargetEffectMask; // Mask req. alive targets struct GOTargetInfo { @@ -666,6 +666,7 @@ class Spell WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType); bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; bool IsValidSingleTargetSpell(Unit const* target) const; + bool IsValidDeadOrAliveTarget(Unit const* target) const; void CalculateDamageDoneForAllTargets(); int32 CalculateDamageDone(Unit *unit, const uint32 effectMask, float *multiplier); void SpellDamageSchoolDmg(SpellEffIndex effIndex); diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 8ba8cce0849..ede63c300c6 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -322,6 +322,21 @@ inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) return spellInfo->AttributesEx3 & SPELL_ATTR_EX3_DEATH_PERSISTENT; } +inline bool IsRequiringDeadTargetSpell(SpellEntry const *spellInfo) +{ + return spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQUIRE_DEAD_TARGET; +} + +inline bool IsAllowingDeadTargetSpell(SpellEntry const *spellInfo) +{ + return spellInfo->AttributesEx2 & SPELL_ATTR_EX2_ALLOW_DEAD_TARGET; +} + +inline bool IsDeadTargetSpell(SpellEntry const *spellInfo) +{ + return IsAllowingDeadTargetSpell(spellInfo) || IsRequiringDeadTargetSpell(spellInfo); +} + inline bool IsNonCombatSpell(SpellEntry const *spellInfo) { return (spellInfo->Attributes & SPELL_ATTR_CANT_USED_IN_COMBAT) != 0; |