Core/Spells: drop last leftovers of hardcoded spell target selection and move it into spellscripts

Closes #1719
Closes #3186
This commit is contained in:
joschiwald committed 2014-01-30 02:40:12 +01:00
1 parent 747184a7c0
commit acd46085d1
7 files changed
+280 -150

No files matched your search

@@ -0,0 +1,3 @@
DELETE FROM `spell_script_names` WHERE `spell_id`=46584;
INSERT INTO `spell_script_names` (`spell_id` ,`ScriptName`) VALUES
(46584,'spell_dk_raise_dead');
+1 -73
View File
@@ -1171,77 +1171,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
// Custom entries
/// @todo remove those
switch (m_spellInfo->Id)
{
case 46584: // Raise Dead
{
if (Player* playerCaster = m_caster->ToPlayer())
{
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
switch ((*itr)->GetTypeId())
{
case TYPEID_UNIT:
case TYPEID_PLAYER:
{
Unit* unitTarget = (*itr)->ToUnit();
if (unitTarget->IsAlive() || !playerCaster->isHonorOrXPTarget(unitTarget)
|| ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
|| (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId()))
break;
AddUnitTarget(unitTarget, effMask, false);
// no break;
}
case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
m_targets.SetDst(*(*itr));
return; // nothing more to do here
default:
break;
}
}
}
return; // don't add targets to target map
}
// Corpse Explosion
case 49158:
case 51325:
case 51326:
case 51327:
case 51328:
// check if our target is not valid (spell can target ghoul or dead unit)
if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() &&
((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
|| m_targets.GetUnitTarget()->isDead())))
{
// remove existing targets
CleanupTargetList();
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
{
switch ((*itr)->GetTypeId())
{
case TYPEID_UNIT:
case TYPEID_PLAYER:
if (!(*itr)->ToUnit()->isDead())
break;
AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false);
return;
default:
break;
}
}
if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
finish(false);
}
return;
default:
break;
}
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex);
if (!targets.empty())
@@ -4866,8 +4795,7 @@ SpellCastResult Spell::CheckCast(bool strict)
uint32 zone, area;
m_caster->GetZoneAndAreaId(zone, area);
SpellCastResult locRes= m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area,
m_caster->GetTypeId() == TYPEID_PLAYER ? m_caster->ToPlayer() : NULL);
SpellCastResult locRes = m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area, m_caster->ToPlayer());
if (locRes != SPELL_CAST_OK)
return locRes;
}
+1 -1
View File
@@ -557,7 +557,7 @@ class Spell
GameObject* focusObject;
// Damage and healing in effects need just calculate
int32 m_damage; // Damge in effects count here
int32 m_damage; // Damage in effects count here
int32 m_healing; // Healing in effects count here
// ******************************************
+3 -58
View File
@@ -682,11 +682,6 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
if (!unitTarget && !gameObjTarget && !itemTarget)
return;
uint32 spell_id = 0;
int32 bp = 0;
bool triggered = true;
SpellCastTargets targets;
// selection by spell family
switch (m_spellInfo->SpellFamilyName)
{
@@ -723,60 +718,10 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
}
}
break;
case SPELLFAMILY_DEATHKNIGHT:
switch (m_spellInfo->Id)
{
case 46584: // Raise Dead
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return;
// Do we have talent Master of Ghouls?
if (m_caster->HasAura(52143))
// summon as pet
bp = 52150;
else
// or guardian
bp = 46585;
if (m_targets.HasDst())
targets.SetDst(*m_targets.GetDstPos());
else
{
targets.SetDst(*m_caster);
// Corpse not found - take reagents (only not triggered cast can take them)
triggered = false;
}
// Remove cooldown - summon spellls have category
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
spell_id = 48289;
break;
// Raise dead - take reagents and trigger summon spells
case 48289:
if (m_targets.HasDst())
targets.SetDst(*m_targets.GetDstPos());
spell_id = CalculateDamage(0, NULL);
break;
}
default:
break;
}
//spells triggered by dummy effect should not miss
if (spell_id)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
if (!spellInfo)
{
TC_LOG_ERROR("spells", "EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
return;
}
targets.SetUnitTarget(unitTarget);
Spell* spell = new Spell(m_caster, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, m_originalCasterGUID, true);
if (bp) spell->SetSpellValue(SPELLVALUE_BASE_POINT0, bp);
spell->prepare(&targets);
}
// pet auras
if (PetAura const* petSpell = sSpellMgr->GetPetAura(m_spellInfo->Id, effIndex))
{
@@ -910,7 +855,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
if (!spellInfo)
{
TC_LOG_DEBUG("spells", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
TC_LOG_ERROR("spells", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
return;
}
@@ -962,7 +907,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex)
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
if (!spellInfo)
{
TC_LOG_DEBUG("spells", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
TC_LOG_ERROR("spells", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
return;
}
+12 -2
View File
@@ -576,16 +576,26 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex)
m_hitPreventDefaultEffectMask |= 1 << effIndex;
}
int32 SpellScript::GetEffectValue()
int32 SpellScript::GetEffectValue() const
{
if (!IsInEffectHook())
{
TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::PreventHitDefaultEffect was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return 0;
}
return m_spell->damage;
}
void SpellScript::SetEffectValue(int32 value)
{
if (!IsInEffectHook())
{
TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::SetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return;
}
m_spell->damage = value;
}
Item* SpellScript::GetCastItem()
{
return m_spell->m_CastItem;
+2 -1
View File
@@ -411,7 +411,8 @@ class SpellScript : public _SpellScript
void PreventHitDefaultEffect(SpellEffIndex effIndex);
// method avalible only in EffectHandler method
int32 GetEffectValue();
int32 GetEffectValue() const;
void SetEffectValue(int32 value);
// returns: cast item if present.
Item* GetCastItem();
+258 -15
View File
@@ -25,6 +25,7 @@
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "Containers.h"
enum DeathKnightSpells
{
@@ -49,6 +50,8 @@ enum DeathKnightSpells
SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622,
SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962,
SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736,
SPELL_DK_MASTER_OF_GHOULS = 52143,
SPELL_DK_RAISE_DEAD_USE_REAGENT = 48289,
SPELL_DK_RUNIC_POWER_ENERGIZE = 49088,
SPELL_DK_SCENT_OF_BLOOD = 50422,
SPELL_DK_SCOURGE_STRIKE_TRIGGERED = 70890,
@@ -63,6 +66,11 @@ enum DeathKnightSpellIcons
DK_ICON_ID_IMPROVED_DEATH_STRIKE = 2751
};
enum Misc
{
NPC_DK_GHOUL = 26125
};
// 50462 - Anti-Magic Shell (on raid member)
class spell_dk_anti_magic_shell_raid : public SpellScriptLoader
{
@@ -311,6 +319,28 @@ class spell_dk_blood_gorged : public SpellScriptLoader
}
};
class CorpseExplosionCheck
{
public:
explicit CorpseExplosionCheck(uint64 casterGUID) : _casterGUID(casterGUID) { }
bool operator()(WorldObject* obj) const
{
if (Unit* target = obj->ToUnit())
{
if ((target->isDead() || (target->GetEntry() == NPC_DK_GHOUL && target->GetOwnerGUID() == _casterGUID))
&& !(target->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)
&& target->GetDisplayId() == target->GetNativeDisplayId())
return false;
}
return true;
}
private:
uint64 _casterGUID;
};
// 49158 - Corpse Explosion (51325, 51326, 51327, 51328)
class spell_dk_corpse_explosion : public SpellScriptLoader
{
@@ -321,41 +351,87 @@ class spell_dk_corpse_explosion : public SpellScriptLoader
{
PrepareSpellScript(spell_dk_corpse_explosion_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
bool Validate(SpellInfo const* spellInfo) OVERRIDE
{
if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE))
return false;
if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL))
if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED)
|| !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE)
|| !sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL)
|| !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue()))
return false;
return true;
}
void HandleDummy(SpellEffIndex /*effIndex*/)
bool Load() OVERRIDE
{
_target = NULL;
return true;
}
void CheckTarget(WorldObject*& target)
{
if (CorpseExplosionCheck(GetCaster()->GetGUID())(target))
target = NULL;
_target = target;
}
void CheckTargets(std::list<WorldObject*>& targets)
{
WorldObject* target = _target;
if (!target)
{
targets.remove_if(CorpseExplosionCheck(GetCaster()->GetGUID()));
if (targets.empty())
{
FinishCast(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
return;
}
target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
else
targets.clear();
}
void HandleDamage(SpellEffIndex effIndex, Unit* target)
{
if (effIndex == EFFECT_0)
GetCaster()->CastCustomSpell(GetSpellInfo()->Effects[EFFECT_1].CalcValue(), SPELLVALUE_BASE_POINT0, GetEffectValue(), target, true);
else if (effIndex == EFFECT_1)
GetCaster()->CastCustomSpell(GetEffectValue(), SPELLVALUE_BASE_POINT0, GetSpell()->CalculateDamage(EFFECT_0, NULL), target, true);
}
void HandleCorpseExplosion(SpellEffIndex effIndex)
{
if (Unit* unitTarget = GetHitUnit())
{
int32 bp = 0;
if (unitTarget->IsAlive()) // Living ghoul as a target
{
bp = int32(unitTarget->CountPctFromMaxHealth(25));
unitTarget->CastCustomSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, &bp, NULL, NULL, false);
unitTarget->CastSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, false);
// Corpse Explosion (Suicide) and Set corpse look handled in SpellScript of SPELL_DK_GHOUL_EXPLODE
}
else // Some corpse
{
bp = GetEffectValue();
GetCaster()->CastCustomSpell(unitTarget, GetSpellInfo()->Effects[EFFECT_1].CalcValue(), &bp, NULL, NULL, true);
HandleDamage(effIndex, unitTarget);
// Corpse Explosion (Suicide)
unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true);
// Set corpse look
GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);
}
// Set corpse look
GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);
}
}
void Register() OVERRIDE
{
OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTarget, EFFECT_0, TARGET_UNIT_TARGET_ANY);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_0, SPELL_EFFECT_DUMMY);
OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_1, SPELL_EFFECT_DUMMY);
}
private:
WorldObject* _target;
};
SpellScript* GetSpellScript() const OVERRIDE
@@ -616,24 +692,34 @@ class spell_dk_ghoul_explode : public SpellScriptLoader
{
PrepareSpellScript(spell_dk_ghoul_explode_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
bool Validate(SpellInfo const* spellInfo) OVERRIDE
{
if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED))
if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED)
|| spellInfo->Effects[EFFECT_2].CalcValue() <= 0)
return false;
return true;
}
void HandleDamage(SpellEffIndex /*effIndex*/)
{
int32 value = int32(GetCaster()->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster())));
SetEffectValue(value);
}
void Suicide(SpellEffIndex /*effIndex*/)
{
if (Unit* unitTarget = GetHitUnit())
{
// Corpse Explosion (Suicide)
unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true);
// Set corpse look
GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);
}
}
void Register() OVERRIDE
{
OnEffectLaunchTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
OnEffectHitTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::Suicide, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
@@ -940,6 +1026,162 @@ class spell_dk_presence : public SpellScriptLoader
}
};
class RaiseDeadCheck
{
public:
explicit RaiseDeadCheck(Player const* caster) : _caster(caster) { }
bool operator()(WorldObject* obj) const
{
if (Unit* target = obj->ToUnit())
{
if (!target->IsAlive()
&& _caster->isHonorOrXPTarget(target)
&& target->GetCreatureType() == CREATURE_TYPE_HUMANOID
&& target->GetDisplayId() == target->GetNativeDisplayId())
return false;
}
return true;
}
private:
Player const* _caster;
};
// 46584 - Raise Dead
class spell_dk_raise_dead : public SpellScriptLoader
{
public:
spell_dk_raise_dead() : SpellScriptLoader("spell_dk_raise_dead") { }
class spell_dk_raise_dead_SpellScript : public SpellScript
{
PrepareSpellScript(spell_dk_raise_dead_SpellScript);
bool Validate(SpellInfo const* spellInfo) OVERRIDE
{
if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue())
|| !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_2].CalcValue())
|| !sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT)
|| !sSpellMgr->GetSpellInfo(SPELL_DK_MASTER_OF_GHOULS))
return false;
return true;
}
bool Load() OVERRIDE
{
_result = SPELL_CAST_OK;
_corpse = false;
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
SpellCastResult CheckCast()
{
/// process spell target selection before cast starts
/// targets of effect_1 are used to check cast
GetSpell()->SelectSpellTargets();
/// cleanup spell target map, and fill it again on normal way
GetSpell()->CleanupTargetList();
/// _result is set in spell target selection
return _result;
}
SpellCastResult CheckReagents()
{
/// @workaround: there is no access to castresult of other spells, check it manually
SpellInfo const* reagentSpell = sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT);
Player* player = GetCaster()->ToPlayer();
if (!player->CanNoReagentCast(reagentSpell))
{
for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
{
if (reagentSpell->Reagent[i] <= 0)
continue;
if (!player->HasItemCount(reagentSpell->Reagent[i], reagentSpell->ReagentCount[i]))
{
Spell::SendCastResult(player, reagentSpell, 0, SPELL_FAILED_REAGENTS);
return SPELL_FAILED_DONT_REPORT;
}
}
}
return SPELL_CAST_OK;
}
void CheckTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(RaiseDeadCheck(GetCaster()->ToPlayer()));
if (targets.empty())
{
if (GetSpell()->getState() == SPELL_STATE_PREPARING)
_result = CheckReagents();
return;
}
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
_corpse = true;
}
void CheckTarget(WorldObject*& target)
{
// Don't add caster to target map, if we found a corpse to raise dead
if (_corpse)
target = NULL;
}
void ConsumeReagents()
{
// No corpse found, take reagents
if (!_corpse)
GetCaster()->CastSpell(GetCaster(), SPELL_DK_RAISE_DEAD_USE_REAGENT, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST));
}
uint32 GetGhoulSpellId()
{
// Do we have talent Master of Ghouls?
if (GetCaster()->HasAura(SPELL_DK_MASTER_OF_GHOULS))
// summon as pet
return GetSpellInfo()->Effects[EFFECT_2].CalcValue();
// or guardian
return GetSpellInfo()->Effects[EFFECT_1].CalcValue();
}
void HandleRaiseDead(SpellEffIndex /*effIndex*/)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(GetGhoulSpellId());
SpellCastTargets targets;
targets.SetDst(*GetHitUnit());
GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK);
}
void Register() OVERRIDE
{
OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY);
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTarget, EFFECT_2, TARGET_UNIT_CASTER);
OnCast += SpellCastFn(spell_dk_raise_dead_SpellScript::ConsumeReagents);
OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY);
}
private:
SpellCastResult _result;
bool _corpse;
};
SpellScript* GetSpellScript() const OVERRIDE
{
return new spell_dk_raise_dead_SpellScript();
}
};
// 59754 Rune Tap - Party
class spell_dk_rune_tap_party : public SpellScriptLoader
{
@@ -1224,6 +1466,7 @@ void AddSC_deathknight_spell_scripts()
new spell_dk_improved_frost_presence();
new spell_dk_improved_unholy_presence();
new spell_dk_presence();
new spell_dk_raise_dead();
new spell_dk_rune_tap_party();
new spell_dk_scent_of_blood();
new spell_dk_scourge_strike();