*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
@@ -823,6 +823,11 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
"TARGET_GAMEOBJECT_AREA_SRC(51), TARGET_GAMEOBJECT_AREA_DST(52)", cond->mSourceEntry); "TARGET_GAMEOBJECT_AREA_SRC(51), TARGET_GAMEOBJECT_AREA_DST(52)", cond->mSourceEntry);
return false; 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; break;
} }
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE: case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
@@ -16388,6 +16388,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
// Do now before stats re-calculation cleanup for ghost state unexpected auras // Do now before stats re-calculation cleanup for ghost state unexpected auras
if (!isAlive()) if (!isAlive())
RemoveAllAurasOnDeath(); RemoveAllAurasOnDeath();
else
RemoveAllAurasRequiringDeadTarget();
//apply all stat bonuses from items and auras //apply all stat bonuses from items and auras
SetCanModifyStats(true); SetCanModifyStats(true);
+3 -2
View File
@@ -12504,9 +12504,10 @@ void Unit::setDeathState(DeathState s)
if (oldDeathState != ALIVE && s == ALIVE) if (oldDeathState != ALIVE && s == ALIVE)
{ {
//_ApplyAllAuraMods();
// Reset display id on resurection - needed by corpse explosion to cleanup after display change // 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());
} }
} }
+1
View File
@@ -1609,6 +1609,7 @@ class Unit : public WorldObject
void RemoveAllAuras(); void RemoveAllAuras();
void RemoveArenaAuras(bool onleave = false); void RemoveArenaAuras(bool onleave = false);
void RemoveAllAurasOnDeath(); void RemoveAllAurasOnDeath();
void RemoveAllAurasRequiringDeadTarget();
void DelayOwnedAuras(uint32 spellId, uint64 caster, int32 delaytime); void DelayOwnedAuras(uint32 spellId, uint64 caster, int32 delaytime);
void _RemoveAllAuraStatMods(); void _RemoveAllAuraStatMods();
@@ -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_ENABLE_AT_DODGE 0x40000000 // 30 Overpower, Wolverine Bite
#define SPELL_ATTR_EX_UNK31 0x80000000 // 31 #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_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_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected
#define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 #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_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_MAIN_HAND 0x00000400 // 10 Main hand weapon required
#define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground #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_UNK13 0x00002000 // 13
#define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag #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 #define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag
@@ -1244,15 +1244,6 @@ void AuraEffect::SendTickImmune(Unit * target, Unit *caster) const
void AuraEffect::PeriodicTick(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())); bool prevented = GetBase()->CallScriptEffectPeriodicHandlers(const_cast<AuraEffect const *>(this), GetBase()->GetApplicationOfTarget(target->GetGUID()));
if (prevented) if (prevented)
return; return;
@@ -1265,6 +1256,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (!caster) if (!caster)
break; 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 // Consecrate ticks can miss and will not show up in the combat log
if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE) caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE)
@@ -1405,6 +1405,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (!caster->isAlive()) if (!caster->isAlive())
return; return;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE) caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE)
return; return;
@@ -1485,6 +1494,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (!caster || !caster->GetHealth()) if (!caster || !caster->GetHealth())
break; break;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
uint32 damage = GetAmount(); uint32 damage = GetAmount();
// do not kill health donator // do not kill health donator
if (caster->GetHealth() < damage) if (caster->GetHealth() < damage)
@@ -1509,6 +1527,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (!caster) if (!caster)
break; break;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
// heal for caster damage (must be alive) // heal for caster damage (must be alive)
if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL && !caster->isAlive()) if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL && !caster->isAlive())
break; break;
@@ -1607,6 +1634,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (GetMiscValue() < 0 || GetMiscValue() >= int8(MAX_POWERS)) if (GetMiscValue() < 0 || GetMiscValue() >= int8(MAX_POWERS))
break; break;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
Powers power = Powers(GetMiscValue()); Powers power = Powers(GetMiscValue());
// power type might have changed between aura applying and tick (druid's shapeshift) // 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) if (GetMiscValue() < 0)
return; return;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
Powers power; Powers power;
if (GetMiscValue() == POWER_ALL) if (GetMiscValue() == POWER_ALL)
power = target->getPowerType(); power = target->getPowerType();
@@ -1742,6 +1787,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (m_amount < 0 || GetMiscValue() >= int8(MAX_POWERS)) if (m_amount < 0 || GetMiscValue() >= int8(MAX_POWERS))
return; return;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
Powers power = Powers(GetMiscValue()); Powers power = Powers(GetMiscValue());
if (target->GetMaxPower(power) == 0) if (target->GetMaxPower(power) == 0)
@@ -1769,6 +1823,15 @@ void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
if (!caster) if (!caster)
return; return;
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
// Check for immune (not use charges) // Check for immune (not use charges)
if (target->IsImmunedToDamage(GetSpellProto())) 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_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_timer = 0; // will set to castime in prepare
m_needAliveTargetMask = 0; m_channelTargetEffectMask = 0;
// determine reflection // determine reflection
m_canReflect = false; m_canReflect = false;
@@ -789,7 +789,7 @@ void Spell::SelectSpellTargets()
{ {
if (ihit->effectMask & mask) if (ihit->effectMask & mask)
{ {
m_needAliveTargetMask |= mask; m_channelTargetEffectMask |= mask;
break; break;
} }
} }
@@ -1682,19 +1682,19 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo *target)
bool Spell::UpdateChanneledTargetList() bool Spell::UpdateChanneledTargetList()
{ {
// Not need check return true // Not need check return true
if (m_needAliveTargetMask == 0) if (m_channelTargetEffectMask == 0)
return true; return true;
uint8 needAliveTargetMask = m_needAliveTargetMask; uint8 channelTargetEffectMask = m_channelTargetEffectMask;
uint8 needAuraMask = 0; uint8 channelAuraMask = 0;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA) if (m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
needAuraMask |= 1<<i; channelAuraMask |= 1<<i;
needAuraMask &= needAliveTargetMask; channelAuraMask &= channelTargetEffectMask;
float range = 0; float range = 0;
if (needAuraMask) if (channelAuraMask)
{ {
range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id)); range = GetSpellMaxRange(m_spellInfo, IsPositiveSpell(m_spellInfo->Id));
if (Player * modOwner = m_caster->GetSpellModOwner()) 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) 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); 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)) if (AuraApplication * aurApp = unit->GetAuraApplication(m_spellInfo->Id, m_originalCasterGUID))
{ {
@@ -1724,13 +1727,13 @@ bool Spell::UpdateChanneledTargetList()
continue; 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 // is all effects from m_needAliveTargetMask have alive targets
return needAliveTargetMask == 0; return channelTargetEffectMask == 0;
} }
// Helper for Chain Healing // Helper for Chain Healing
@@ -4092,7 +4095,7 @@ void Spell::WriteSpellGoTargets(WorldPacket * data)
if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits
{ {
*data << uint64(ihit->targetGUID); *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 // Reset m_needAliveTargetMask for non channeled spell
if (!IsChanneledSpell(m_spellInfo)) if (!IsChanneledSpell(m_spellInfo))
m_needAliveTargetMask = 0; m_channelTargetEffectMask = 0;
} }
void Spell::SendLogExecute() void Spell::SendLogExecute()
@@ -6915,6 +6918,15 @@ bool Spell::IsValidSingleTargetSpell(Unit const* target) const
return true; 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() void Spell::CalculateDamageDoneForAllTargets()
{ {
float multiplier[MAX_SPELL_EFFECTS]; float multiplier[MAX_SPELL_EFFECTS];
+2 -1
View File
@@ -631,7 +631,7 @@ class Spell
int32 damage; int32 damage;
}; };
std::list<TargetInfo> m_UniqueTargetInfo; std::list<TargetInfo> m_UniqueTargetInfo;
uint8 m_needAliveTargetMask; // Mask req. alive targets uint8 m_channelTargetEffectMask; // Mask req. alive targets
struct GOTargetInfo struct GOTargetInfo
{ {
@@ -666,6 +666,7 @@ class Spell
WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType); WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType);
bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; bool IsValidSingleTargetEffect(Unit const* target, Targets type) const;
bool IsValidSingleTargetSpell(Unit const* target) const; bool IsValidSingleTargetSpell(Unit const* target) const;
bool IsValidDeadOrAliveTarget(Unit const* target) const;
void CalculateDamageDoneForAllTargets(); void CalculateDamageDoneForAllTargets();
int32 CalculateDamageDone(Unit *unit, const uint32 effectMask, float *multiplier); int32 CalculateDamageDone(Unit *unit, const uint32 effectMask, float *multiplier);
void SpellDamageSchoolDmg(SpellEffIndex effIndex); 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; 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) inline bool IsNonCombatSpell(SpellEntry const *spellInfo)
{ {
return (spellInfo->Attributes & SPELL_ATTR_CANT_USED_IN_COMBAT) != 0; return (spellInfo->Attributes & SPELL_ATTR_CANT_USED_IN_COMBAT) != 0;