Core/SpellScript: Implemented OnObjectTargetSelect hook for use with spell target that selects a single object

This commit is contained in:
Shauren
2012-07-03 12:35:06 +02:00
parent 96014a70cb
commit 537caf33e9
4 changed files with 115 additions and 34 deletions
+80 -33
View File
@@ -914,17 +914,25 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa
switch (targetType.GetTarget()) switch (targetType.GetTarget())
{ {
case TARGET_UNIT_CHANNEL_TARGET: case TARGET_UNIT_CHANNEL_TARGET:
{
WorldObject* target = ObjectAccessor::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID());
CallScriptObjectTargetSelectHandlers(target, effIndex);
// unit target may be no longer avalible - teleported out of map for example // unit target may be no longer avalible - teleported out of map for example
if (Unit* target = Unit::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID())) if (target && target->ToUnit())
AddUnitTarget(target, 1 << effIndex); AddUnitTarget(target->ToUnit(), 1 << effIndex);
else else
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
break; break;
}
case TARGET_DEST_CHANNEL_TARGET: case TARGET_DEST_CHANNEL_TARGET:
if (channeledSpell->m_targets.HasDst()) if (channeledSpell->m_targets.HasDst())
m_targets.SetDst(channeledSpell->m_targets); m_targets.SetDst(channeledSpell->m_targets);
else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, channeledSpell->m_targets.GetObjectTargetGUID())) else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, channeledSpell->m_targets.GetObjectTargetGUID()))
{
CallScriptObjectTargetSelectHandlers(target, effIndex);
if (target)
m_targets.SetDst(*target); m_targets.SetDst(*target);
}
else else
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex); sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
break; break;
@@ -1002,6 +1010,8 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
return; return;
} }
CallScriptObjectTargetSelectHandlers(target, effIndex);
switch (targetType.GetObjectType()) switch (targetType.GetObjectType())
{ {
case TARGET_OBJECT_TYPE_UNIT: case TARGET_OBJECT_TYPE_UNIT:
@@ -1492,27 +1502,27 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT
void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{ {
WorldObject* target = NULL;
bool checkIfValid = true;
switch (targetType.GetTarget()) switch (targetType.GetTarget())
{ {
case TARGET_UNIT_CASTER: case TARGET_UNIT_CASTER:
AddUnitTarget(m_caster, 1 << effIndex, false); target = m_caster;
checkIfValid = false;
break; break;
case TARGET_UNIT_MASTER: case TARGET_UNIT_MASTER:
if (Unit* owner = m_caster->GetCharmerOrOwner()) target = m_caster->GetCharmerOrOwner();
AddUnitTarget(owner, 1 << effIndex);
break; break;
case TARGET_UNIT_PET: case TARGET_UNIT_PET:
if (Guardian* pet = m_caster->GetGuardianPet()) target = m_caster->GetGuardianPet();
AddUnitTarget(pet, 1 << effIndex);
break; break;
case TARGET_UNIT_SUMMONER: case TARGET_UNIT_SUMMONER:
if (m_caster->isSummon()) if (m_caster->isSummon())
if (Unit* unit = m_caster->ToTempSummon()->GetSummoner()) target = m_caster->ToTempSummon()->GetSummoner();
AddUnitTarget(unit, 1 << effIndex);
break; break;
case TARGET_UNIT_VEHICLE: case TARGET_UNIT_VEHICLE:
if (Unit *vehicle = m_caster->GetVehicleBase()) target = m_caster->GetVehicleBase();
AddUnitTarget(vehicle, 1 << effIndex);
break; break;
case TARGET_UNIT_PASSENGER_0: case TARGET_UNIT_PASSENGER_0:
case TARGET_UNIT_PASSENGER_1: case TARGET_UNIT_PASSENGER_1:
@@ -1523,26 +1533,38 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli
case TARGET_UNIT_PASSENGER_6: case TARGET_UNIT_PASSENGER_6:
case TARGET_UNIT_PASSENGER_7: case TARGET_UNIT_PASSENGER_7:
if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle()) if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0)) target = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0);
AddUnitTarget(unit, 1 << effIndex);
break; break;
default: default:
break; break;
} }
CallScriptObjectTargetSelectHandlers(target, effIndex);
if (target && target->ToUnit())
AddUnitTarget(target->ToUnit(), 1 << effIndex, checkIfValid);
} }
void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType)
{ {
ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!");
if (Unit* unit = m_targets.GetUnitTarget())
AddUnitTarget(unit, 1 << effIndex, true, false);
else if (GameObject* gobj = m_targets.GetGOTarget())
AddGOTarget(gobj, 1 << effIndex);
else
AddItemTarget(m_targets.GetItemTarget(), 1 << effIndex);
if (WorldObject* target = m_targets.GetObjectTarget()) WorldObject* target = m_targets.GetObjectTarget();
CallScriptObjectTargetSelectHandlers(target, effIndex);
if (target)
{
if (Unit* unit = target->ToUnit())
AddUnitTarget(unit, 1 << effIndex, true, false);
else if (GameObject* gobj = target->ToGameObject())
AddGOTarget(gobj, 1 << effIndex);
SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex); SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex);
}
// Script hook can remove object target and we would wrongly land here
else if (Item* item = m_targets.GetItemTarget())
AddItemTarget(item, 1 << effIndex);
} }
void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask)
@@ -1734,9 +1756,12 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
case SPELL_EFFECT_SUMMON_PLAYER: case SPELL_EFFECT_SUMMON_PLAYER:
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->GetSelection()) if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->GetSelection())
{ {
Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection()); WorldObject* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection());
if (target)
AddUnitTarget(target, 1 << effIndex, false); CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex));
if (target && target->ToPlayer())
AddUnitTarget(target->ToUnit(), 1 << effIndex, false);
} }
return; return;
default: default:
@@ -1752,6 +1777,8 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
if (!targetMask) if (!targetMask)
return; return;
WorldObject* target = NULL;
switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType()) switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType())
{ {
// add explicit object target or self to the target map // add explicit object target or self to the target map
@@ -1760,40 +1787,46 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
if (targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK)) if (targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK))
{ {
if (Unit* unitTarget = m_targets.GetUnitTarget()) if (Unit* unitTarget = m_targets.GetUnitTarget())
AddUnitTarget(unitTarget, 1 << effIndex, false); target = unitTarget;
else if (targetMask & TARGET_FLAG_CORPSE_MASK) else if (targetMask & TARGET_FLAG_CORPSE_MASK)
{ {
if (Corpse* corpseTarget = m_targets.GetCorpseTarget()) if (Corpse* corpseTarget = m_targets.GetCorpseTarget())
{ {
// TODO: this is a workaround - corpses should be added to spell target map too, but we can't do that so we add owner instead // TODO: this is a workaround - corpses should be added to spell target map too, but we can't do that so we add owner instead
if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID())) if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
AddUnitTarget(owner, 1 << effIndex, false); target = owner;
} }
} }
else //if (targetMask & TARGET_FLAG_UNIT_MASK) else //if (targetMask & TARGET_FLAG_UNIT_MASK)
{ target = m_caster;
AddUnitTarget(m_caster, 1 << effIndex, false);
}
} }
if (targetMask & TARGET_FLAG_ITEM_MASK) if (targetMask & TARGET_FLAG_ITEM_MASK)
{ {
if (Item* itemTarget = m_targets.GetItemTarget()) if (Item* itemTarget = m_targets.GetItemTarget())
AddItemTarget(itemTarget, 1 << effIndex); AddItemTarget(itemTarget, 1 << effIndex);
return;
} }
if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK) if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK)
{ target = m_targets.GetGOTarget();
if (GameObject* gObjTarget = m_targets.GetGOTarget())
AddGOTarget(gObjTarget, 1 << effIndex);
}
break; break;
// add self to the target map // add self to the target map
case EFFECT_IMPLICIT_TARGET_CASTER: case EFFECT_IMPLICIT_TARGET_CASTER:
if (targetMask & TARGET_FLAG_UNIT_MASK) if (targetMask & TARGET_FLAG_UNIT_MASK)
AddUnitTarget(m_caster, 1 << effIndex, false); target = m_caster;
break; break;
default: default:
break; break;
} }
CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex));
if (target)
{
if (target->ToUnit())
AddUnitTarget(target->ToUnit(), 1 << effIndex, false);
else if (target->ToGameObject())
AddGOTarget(target->ToGameObject(), 1 << effIndex);
}
} }
uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList) uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList)
@@ -7053,6 +7086,20 @@ void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& ta
} }
} }
void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex)
{
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT);
std::list<SpellScript::ObjectTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin();
for (; hookItr != hookItrEnd; ++hookItr)
if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex))
(*hookItr).Call(*scritr, target);
(*scritr)->_FinishScriptCall();
}
}
bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const
{ {
bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER)); bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
+1
View File
@@ -631,6 +631,7 @@ class Spell
void CallScriptOnHitHandlers(); void CallScriptOnHitHandlers();
void CallScriptAfterHitHandlers(); void CallScriptAfterHitHandlers();
void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex); void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex);
void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex);
std::list<SpellScript*> m_loadedScripts; std::list<SpellScript*> m_loadedScripts;
struct HitTriggerSpell struct HitTriggerSpell
+15
View File
@@ -267,6 +267,17 @@ void SpellScript::ObjectAreaTargetSelectHandler::Call(SpellScript* spellScript,
(spellScript->*pObjectAreaTargetSelectHandlerScript)(targets); (spellScript->*pObjectAreaTargetSelectHandlerScript)(targets);
} }
SpellScript::ObjectTargetSelectHandler::ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType)
: TargetHook(_effIndex, _targetType, false)
{
pObjectTargetSelectHandlerScript = _pObjectTargetSelectHandlerScript;
}
void SpellScript::ObjectTargetSelectHandler::Call(SpellScript* spellScript, WorldObject*& target)
{
(spellScript->*pObjectTargetSelectHandlerScript)(target);
}
bool SpellScript::_Validate(SpellInfo const* entry) bool SpellScript::_Validate(SpellInfo const* entry)
{ {
for (std::list<EffectHandler>::iterator itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr) for (std::list<EffectHandler>::iterator itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr)
@@ -289,6 +300,10 @@ bool SpellScript::_Validate(SpellInfo const* entry)
if (!(*itr).GetAffectedEffectsMask(entry)) if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<ObjectTargetSelectHandler>::iterator itr = OnObjectTargetSelect.begin(); itr != OnObjectTargetSelect.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
return _SpellScript::_Validate(entry); return _SpellScript::_Validate(entry);
} }
+18
View File
@@ -132,6 +132,7 @@ enum SpellScriptHookType
SPELL_SCRIPT_HOOK_HIT, SPELL_SCRIPT_HOOK_HIT,
SPELL_SCRIPT_HOOK_AFTER_HIT, SPELL_SCRIPT_HOOK_AFTER_HIT,
SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT, SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT,
SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT,
SPELL_SCRIPT_HOOK_CHECK_CAST, SPELL_SCRIPT_HOOK_CHECK_CAST,
SPELL_SCRIPT_HOOK_BEFORE_CAST, SPELL_SCRIPT_HOOK_BEFORE_CAST,
SPELL_SCRIPT_HOOK_ON_CAST, SPELL_SCRIPT_HOOK_ON_CAST,
@@ -155,6 +156,7 @@ class SpellScript : public _SpellScript
typedef void(CLASSNAME::*SpellHitFnType)(); \ typedef void(CLASSNAME::*SpellHitFnType)(); \
typedef void(CLASSNAME::*SpellCastFnType)(); \ typedef void(CLASSNAME::*SpellCastFnType)(); \
typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \
typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&);
SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript)
@@ -216,12 +218,22 @@ class SpellScript : public _SpellScript
SpellObjectAreaTargetSelectFnType pObjectAreaTargetSelectHandlerScript; SpellObjectAreaTargetSelectFnType pObjectAreaTargetSelectHandlerScript;
}; };
class ObjectTargetSelectHandler : public TargetHook
{
public:
ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType);
void Call(SpellScript* spellScript, WorldObject*& targets);
private:
SpellObjectTargetSelectFnType pObjectTargetSelectHandlerScript;
};
#define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ #define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CastHandlerFunction : public SpellScript::CastHandler { public: CastHandlerFunction(SpellCastFnType _pCastHandlerScript) : SpellScript::CastHandler((SpellScript::SpellCastFnType)_pCastHandlerScript) {} }; \ class CastHandlerFunction : public SpellScript::CastHandler { public: CastHandlerFunction(SpellCastFnType _pCastHandlerScript) : SpellScript::CastHandler((SpellScript::SpellCastFnType)_pCastHandlerScript) {} }; \
class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) {} }; \ class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) {} }; \
class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) {} }; \ class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) {} }; \
class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) {} }; \ class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) {} }; \
class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) {} };
#define PrepareSpellScript(CLASSNAME) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) #define PrepareSpellScript(CLASSNAME) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
public: public:
@@ -280,10 +292,16 @@ class SpellScript : public _SpellScript
HookList<ObjectAreaTargetSelectHandler> OnObjectAreaTargetSelect; HookList<ObjectAreaTargetSelectHandler> OnObjectAreaTargetSelect;
#define SpellObjectAreaTargetSelectFn(F, I, N) ObjectAreaTargetSelectHandlerFunction(&F, I, N) #define SpellObjectAreaTargetSelectFn(F, I, N) ObjectAreaTargetSelectHandlerFunction(&F, I, N)
// example: OnObjectTargetSelect += SpellObjectTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier);
// where function is void function(WorldObject*& target)
HookList<ObjectTargetSelectHandler> OnObjectTargetSelect;
#define SpellObjectTargetSelectFn(F, I, N) ObjectTargetSelectHandlerFunction(&F, I, N)
// hooks are executed in following order, at specified event of spell: // hooks are executed in following order, at specified event of spell:
// 1. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled // 1. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled
// 2. OnCheckCast - allows to override result of CheckCast function // 2. OnCheckCast - allows to override result of CheckCast function
// 3a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets) // 3a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets)
// 3b. OnObjectTargetSelect - executed just before adding selected target to final target list (for single unit targets)
// 4. OnCast - executed just before spell is launched (creates missile) or executed // 4. OnCast - executed just before spell is launched (creates missile) or executed
// 5. AfterCast - executed after spell missile is launched and immediate spell actions are done // 5. AfterCast - executed after spell missile is launched and immediate spell actions are done
// 6. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched // 6. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched