*Allow channeled spells to be casted on dead target

*Define relted spell attributes

--HG--
branch : trunk
This commit is contained in:
QAston
2010-08-30 17:32:51 +02:00
parent 405f312918
commit a8de57559b
9 changed files with 129 additions and 29 deletions
@@ -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()))
{
+27 -15
View File
@@ -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];
+2 -1
View File
@@ -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);
+15
View File
@@ -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;