Core/Spells:

* Implemented on CheckCast spell script hook
* Added possibility to send SPELL_FAILED_CUSTOM_ERROR and added enum with all possible options for it

Scripts/Spells:
* Added example script for CheckCast hook with SPELL_FAILED_CUSTOM_ERROR (profession research and Book of Glyph Mastery)
This commit is contained in:
Shauren
2011-03-04 21:19:43 +01:00
parent a9582964d3
commit 7120f1eff8
12 changed files with 262 additions and 8 deletions
+30 -2
View File
@@ -425,6 +425,7 @@ m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, Caster)),
m_caster(Caster), m_spellValue(new SpellValue(m_spellInfo))
{
m_customAttr = sSpellMgr->GetSpellCustomAttr(m_spellInfo->Id);
m_customError = SPELL_CUSTOM_ERROR_NONE;
m_skipCheck = skipCheck;
m_selfContainer = NULL;
m_referencedFromCurrentSpell = false;
@@ -3742,10 +3743,10 @@ void Spell::SendCastResult(SpellCastResult result)
if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
return;
SendCastResult((Player*)m_caster,m_spellInfo,m_cast_count,result);
SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError);
}
void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result)
void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/)
{
if (result == SPELL_CAST_OK)
return;
@@ -3807,6 +3808,9 @@ void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 ca
data << uint32(pProto->ItemLimitCategory);
break;
}
case SPELL_FAILED_CUSTOM_ERROR:
data << uint32(customError);
break;
default:
break;
}
@@ -5009,6 +5013,11 @@ SpellCastResult Spell::CheckCast(bool strict)
return castResult;
}
// script hook
castResult = CallScriptCheckCastHandlers();
if (castResult != SPELL_CAST_OK)
return castResult;
for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
{
// for effects of spells that have only one target
@@ -7216,6 +7225,25 @@ void Spell::PrepareScriptHitHandlers()
(*scritr)->_InitHit();
}
SpellCastResult Spell::CallScriptCheckCastHandlers()
{
SpellCastResult retVal = SPELL_CAST_OK;
for (std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CHECK_CAST);
std::list<SpellScript::CheckCastHandler>::iterator hookItrEnd = (*scritr)->OnCheckCast.end(), hookItr = (*scritr)->OnCheckCast.begin();
for (; hookItr != hookItrEnd; ++hookItr)
{
SpellCastResult tempResult = (*hookItr).Call(*scritr);
if (retVal == SPELL_CAST_OK)
retVal = tempResult;
}
(*scritr)->_FinishScriptCall();
}
return retVal;
}
bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex)
{
// execute script effect handler hooks and check if effects was prevented
+3 -1
View File
@@ -470,7 +470,7 @@ class Spell
void CheckSrc() { if (!m_targets.HasSrc()) m_targets.setSrc(*m_caster); }
void CheckDst() { if (!m_targets.HasDst()) m_targets.setDst(*m_caster); }
static void SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result);
static void SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE);
void SendCastResult(SpellCastResult result);
void SendSpellStart();
void SendSpellGo();
@@ -503,6 +503,7 @@ class Spell
uint32 m_preCastSpell;
SpellCastTargets m_targets;
int8 m_comboPointGain;
SpellCustomErrors m_customError;
UsedSpellMods m_appliedMods;
@@ -687,6 +688,7 @@ class Spell
// Scripting system
void LoadScripts();
SpellCastResult CallScriptCheckCastHandlers();
void PrepareScriptHitHandlers();
bool CallScriptEffectHandlers(SpellEffIndex effIndex);
void CallScriptBeforeHitHandlers();
+1 -1
View File
@@ -5126,7 +5126,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
return;
// learn random explicit discovery recipe (if any)
if (uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster))
if (uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, m_caster->ToPlayer()))
m_caster->ToPlayer()->learnSpell(discoveredSpell, false);
return;
}
+21
View File
@@ -146,6 +146,16 @@ std::string _SpellScript::EffectAuraNameCheck::ToString()
}
}
SpellScript::CheckCastHandler::CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript)
{
_checkCastHandlerScript = checkCastHandlerScript;
}
SpellCastResult SpellScript::CheckCastHandler::Call(SpellScript* spellScript)
{
return (spellScript->*_checkCastHandlerScript)();
}
SpellScript::EffectHandler::EffectHandler(SpellEffectFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName)
: _SpellScript::EffectNameCheck(_effName), _SpellScript::EffectHook(_effIndex)
{
@@ -445,6 +455,17 @@ void SpellScript::FinishCast(SpellCastResult result)
m_spell->finish(result == SPELL_CAST_OK);
}
void SpellScript::SetCustomCastResultMessage(SpellCustomErrors result)
{
if (!IsInCheckCastHook())
{
sLog->outError("TSCR: Script: `%s` Spell: `%u`: function SpellScript::SetCustomCastResultMessage was called while spell not in check cast phase!", m_scriptName->c_str(), m_scriptSpellId);
return;
}
m_spell->m_customError = result;
}
bool AuraScript::_Validate(SpellEntry const * entry)
{
for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr)
+25 -4
View File
@@ -121,11 +121,12 @@ enum SpellScriptHookType
SPELL_SCRIPT_HOOK_HIT,
SPELL_SCRIPT_HOOK_AFTER_HIT,
SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT,
SPELL_SCRIPT_HOOK_CHECK_CAST,
};
#define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT
#define HOOK_SPELL_HIT_END SPELL_SCRIPT_HOOK_AFTER_HIT + 1
#define HOOK_SPELL_START SPELL_SCRIPT_HOOK_EFFECT
#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT + 1
#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_CHECK_CAST + 1
#define HOOK_SPELL_COUNT HOOK_SPELL_END - HOOK_SPELL_START
class SpellScript : public _SpellScript
@@ -134,12 +135,22 @@ class SpellScript : public _SpellScript
// DO NOT OVERRIDE THESE IN SCRIPTS
public:
#define SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \
typedef SpellCastResult(CLASSNAME::*SpellCheckCastFnType)(); \
typedef void(CLASSNAME::*SpellEffectFnType)(SpellEffIndex); \
typedef void(CLASSNAME::*SpellHitFnType)(); \
typedef void(CLASSNAME::*SpellUnitTargetFnType)(std::list<Unit*>&); \
SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript)
class CheckCastHandler
{
public:
CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript);
SpellCastResult Call(SpellScript* spellScript);
private:
SpellCheckCastFnType _checkCastHandlerScript;
};
class EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook
{
public:
@@ -173,6 +184,7 @@ class SpellScript : public _SpellScript
};
#define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
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 HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) {} }; \
class UnitTargetHandlerFunction : public SpellScript::UnitTargetHandler { public: UnitTargetHandlerFunction(SpellUnitTargetFnType _pUnitTargetHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::UnitTargetHandler((SpellScript::SpellUnitTargetFnType)_pUnitTargetHandlerScript, _effIndex, _targetType) {} }; \
@@ -186,8 +198,9 @@ class SpellScript : public _SpellScript
bool _IsDefaultEffectPrevented(SpellEffIndex effIndex) { return m_hitPreventDefaultEffectMask & (1<<effIndex); }
void _PrepareScriptCall(SpellScriptHookType hookType);
void _FinishScriptCall();
bool IsInHitPhase() { return (m_currentScriptState >= HOOK_SPELL_HIT_START && m_currentScriptState < HOOK_SPELL_HIT_END); }
bool IsInEffectHook() { return (m_currentScriptState == SPELL_SCRIPT_HOOK_EFFECT); }
bool IsInCheckCastHook() const { return m_currentScriptState == SPELL_SCRIPT_HOOK_CHECK_CAST; }
bool IsInHitPhase() const { return (m_currentScriptState >= HOOK_SPELL_HIT_START && m_currentScriptState < HOOK_SPELL_HIT_END); }
bool IsInEffectHook() const { return (m_currentScriptState == SPELL_SCRIPT_HOOK_EFFECT); }
private:
Spell * m_spell;
uint8 m_hitPreventEffectMask;
@@ -197,6 +210,12 @@ class SpellScript : public _SpellScript
// SpellScript interface
// hooks to which you can attach your functions
//
// example: OnCheckCast += SpellCheckCastFn();
// where function is SpellCastResult function()
HookList<CheckCastHandler> OnCheckCast;
#define SpellCheckCastFn(F) CheckCastHandlerFunction(&F)
// example: OnEffect += SpellEffectFn(class::function, EffectIndexSpecifier, EffectNameSpecifier);
// where function is void function(SpellEffIndex effIndex)
HookList<EffectHandler> OnEffect;
@@ -294,6 +313,8 @@ class SpellScript : public _SpellScript
// finishes spellcast prematurely with selected error message
void FinishCast(SpellCastResult result);
void SetCustomCastResultMessage(SpellCustomErrors result);
};
// AuraScript interface - enum used for runtime checks of script function calls
@@ -454,7 +475,7 @@ class AuraScript : public _SpellScript
// executed when periodic aura effect is updated
// example: OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
// where function is: void function (AuraEffect const * aurEff);
// where function is: void function (AuraEffect * aurEff);
HookList<EffectUpdatePeriodicHandler> OnEffectUpdatePeriodic;
#define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandlerFunction(&F, I, N)