aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQAston <none@none>2010-08-30 17:32:51 +0200
committerQAston <none@none>2010-08-30 17:32:51 +0200
commita8de57559bb98dafb1685ce5dda2392d26844f06 (patch)
tree3b30787b25833d596733953364ecc26d59aab87e /src
parent405f312918136510fde921403ffffa315bdbcb4b (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.cpp5
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp5
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp81
-rw-r--r--src/server/game/Spells/Spell.cpp42
-rw-r--r--src/server/game/Spells/Spell.h3
-rw-r--r--src/server/game/Spells/SpellMgr.h15
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;