mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-17 13:39:46 -04:00
Core/AI: OnSpellCast, OnSpellFailed, OnSpellStart hooks (#27704)
(cherry picked from commit 3dca705acc)
This commit is contained in:
@@ -33,7 +33,6 @@ class PlayerAI;
|
||||
class WorldObject;
|
||||
struct Position;
|
||||
enum class QuestGiverStatus : uint32;
|
||||
enum SpellFinishReason : uint8;
|
||||
|
||||
typedef std::vector<AreaBoundary const*> CreatureBoundary;
|
||||
|
||||
@@ -140,8 +139,17 @@ class TC_GAME_API CreatureAI : public UnitAI
|
||||
// Called when spell hits a target
|
||||
virtual void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* /*spellInfo*/) { }
|
||||
|
||||
// Called when a spell either finishes, interrupts or cancels a spell cast
|
||||
virtual void OnSpellCastFinished(SpellInfo const* /*spell*/, SpellFinishReason /*reason*/) { }
|
||||
// Called when a spell finishes
|
||||
virtual void OnSpellCast(SpellInfo const* /*spell*/) { }
|
||||
|
||||
// Called when a spell fails
|
||||
virtual void OnSpellFailed(SpellInfo const* /*spell*/) { }
|
||||
|
||||
// Called when a spell starts
|
||||
virtual void OnSpellStart(SpellInfo const* /*spell*/) { }
|
||||
|
||||
// Called when a channeled spell finishes
|
||||
virtual void OnChannelFinished(SpellInfo const* /*spell*/) { }
|
||||
|
||||
// Should return true if the NPC is currently being escorted
|
||||
virtual bool IsEscorted() const { return false; }
|
||||
|
||||
@@ -620,6 +620,21 @@ void SmartAI::SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo)
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_SPELLHIT_TARGET, target->ToUnit(), 0, 0, false, spellInfo, target->ToGameObject());
|
||||
}
|
||||
|
||||
void SmartAI::OnSpellCast(SpellInfo const* spellInfo)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELL_CAST, nullptr, 0, 0, false, spellInfo);
|
||||
}
|
||||
|
||||
void SmartAI::OnSpellFailed(SpellInfo const* spellInfo)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELL_FAILED, nullptr, 0, 0, false, spellInfo);
|
||||
}
|
||||
|
||||
void SmartAI::OnSpellStart(SpellInfo const* spellInfo)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELL_START, nullptr, 0, 0, false, spellInfo);
|
||||
}
|
||||
|
||||
void SmartAI::DamageTaken(Unit* doneBy, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_DAMAGED, doneBy, damage);
|
||||
|
||||
@@ -123,6 +123,15 @@ class TC_GAME_API SmartAI : public CreatureAI
|
||||
// Called when spell hits a target
|
||||
void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override;
|
||||
|
||||
// Called when a spell finishes
|
||||
void OnSpellCast(SpellInfo const* spellInfo) override;
|
||||
|
||||
// Called when a spell fails
|
||||
void OnSpellFailed(SpellInfo const* spellInfo) override;
|
||||
|
||||
// Called when a spell starts
|
||||
void OnSpellStart(SpellInfo const* spellInfo) override;
|
||||
|
||||
// Called at any Damage from any attacker (before damage apply)
|
||||
void DamageTaken(Unit* doneBy, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override;
|
||||
|
||||
|
||||
@@ -3164,6 +3164,20 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_EVENT_ON_SPELL_CAST:
|
||||
case SMART_EVENT_ON_SPELL_FAILED:
|
||||
case SMART_EVENT_ON_SPELL_START:
|
||||
{
|
||||
if (!spell)
|
||||
return;
|
||||
|
||||
if (spell->Id != e.event.spellCast.spell)
|
||||
return;
|
||||
|
||||
RecalcTimer(e, e.event.spellCast.cooldownMin, e.event.spellCast.cooldownMax);
|
||||
ProcessAction(e, nullptr, 0, 0, bvar, spell);
|
||||
break;
|
||||
}
|
||||
case SMART_EVENT_OOC_LOS:
|
||||
{
|
||||
if (!me || me->IsEngaged())
|
||||
|
||||
@@ -841,6 +841,9 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
|
||||
case SMART_EVENT_SCENE_CANCEL: return NO_PARAMS;
|
||||
case SMART_EVENT_SCENE_COMPLETE: return NO_PARAMS;
|
||||
case SMART_EVENT_SUMMONED_UNIT_DIES: return sizeof(SmartEvent::summoned);
|
||||
case SMART_EVENT_ON_SPELL_CAST: return sizeof(SmartEvent::spellCast);
|
||||
case SMART_EVENT_ON_SPELL_FAILED: return sizeof(SmartEvent::spellCast);
|
||||
case SMART_EVENT_ON_SPELL_START: return sizeof(SmartEvent::spellCast);
|
||||
default:
|
||||
TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u is using an event with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
@@ -1172,6 +1175,17 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
if (!IsMinMaxValid(e, e.event.spellHit.cooldownMin, e.event.spellHit.cooldownMax))
|
||||
return false;
|
||||
break;
|
||||
case SMART_EVENT_ON_SPELL_CAST:
|
||||
case SMART_EVENT_ON_SPELL_FAILED:
|
||||
case SMART_EVENT_ON_SPELL_START:
|
||||
{
|
||||
if (!IsSpellValid(e, e.event.spellCast.spell))
|
||||
return false;
|
||||
|
||||
if (!IsMinMaxValid(e, e.event.spellCast.cooldownMin, e.event.spellCast.cooldownMax))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SMART_EVENT_OOC_LOS:
|
||||
case SMART_EVENT_IC_LOS:
|
||||
if (!IsMinMaxValid(e, e.event.los.cooldownMin, e.event.los.cooldownMax))
|
||||
|
||||
@@ -181,8 +181,11 @@ enum SMART_EVENT
|
||||
SMART_EVENT_SCENE_CANCEL = 80, // none
|
||||
SMART_EVENT_SCENE_COMPLETE = 81, // none
|
||||
SMART_EVENT_SUMMONED_UNIT_DIES = 82, // CreatureId(0 all), CooldownMin, CooldownMax
|
||||
SMART_EVENT_ON_SPELL_CAST = 83, // SpellID, CooldownMin, CooldownMax
|
||||
SMART_EVENT_ON_SPELL_FAILED = 84, // SpellID, CooldownMin, CooldownMax
|
||||
SMART_EVENT_ON_SPELL_START = 85, // SpellID, CooldownMin, CooldownMax
|
||||
|
||||
SMART_EVENT_END = 83
|
||||
SMART_EVENT_END = 86
|
||||
};
|
||||
|
||||
struct SmartEvent
|
||||
@@ -412,6 +415,13 @@ struct SmartEvent
|
||||
uint32 cooldownMax;
|
||||
} counter;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 spell;
|
||||
uint32 cooldownMin;
|
||||
uint32 cooldownMax;
|
||||
} spellCast;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 param1;
|
||||
@@ -1543,6 +1553,9 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
|
||||
{SMART_EVENT_SCENE_CANCEL, SMART_SCRIPT_TYPE_MASK_SCENE },
|
||||
{SMART_EVENT_SCENE_COMPLETE, SMART_SCRIPT_TYPE_MASK_SCENE },
|
||||
{SMART_EVENT_SUMMONED_UNIT_DIES, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
|
||||
{SMART_EVENT_ON_SPELL_CAST, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
{SMART_EVENT_ON_SPELL_FAILED, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
{SMART_EVENT_ON_SPELL_START, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
};
|
||||
|
||||
enum SmartEventFlags
|
||||
|
||||
@@ -2922,7 +2922,7 @@ void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool wi
|
||||
}
|
||||
|
||||
if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
|
||||
ToCreature()->AI()->OnSpellCastFinished(spell->GetSpellInfo(), SPELL_FINISHED_CANCELED);
|
||||
ToCreature()->AI()->OnSpellFailed(spell->GetSpellInfo());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3341,6 +3341,11 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const
|
||||
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_GCD))
|
||||
TriggerGlobalCooldown();
|
||||
|
||||
// Call CreatureAI hook OnSpellStart
|
||||
if (Creature* caster = m_originalCaster->ToCreature())
|
||||
if (caster->IsAIEnabled())
|
||||
caster->AI()->OnSpellStart(GetSpellInfo());
|
||||
|
||||
if (willCastDirectly)
|
||||
cast(true);
|
||||
}
|
||||
@@ -3707,10 +3712,10 @@ void Spell::_cast(bool skipCheck)
|
||||
|
||||
Unit::ProcSkillsAndAuras(m_originalCaster, nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr);
|
||||
|
||||
// Call CreatureAI hook OnSpellCastFinished
|
||||
// Call CreatureAI hook OnSpellCast
|
||||
if (Creature* caster = m_originalCaster->ToCreature())
|
||||
if (caster->IsAIEnabled())
|
||||
caster->AI()->OnSpellCastFinished(GetSpellInfo(), SPELL_FINISHED_SUCCESSFUL_CAST);
|
||||
caster->AI()->OnSpellCast(GetSpellInfo());
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
@@ -4068,7 +4073,7 @@ void Spell::update(uint32 difftime)
|
||||
// We call the hook here instead of in Spell::finish because we only want to call it for completed channeling. Everything else is handled by interrupts
|
||||
if (Creature* creatureCaster = m_caster->ToCreature())
|
||||
if (creatureCaster->IsAIEnabled())
|
||||
creatureCaster->AI()->OnSpellCastFinished(m_spellInfo, SPELL_FINISHED_CHANNELING_COMPLETE);
|
||||
creatureCaster->AI()->OnChannelFinished(m_spellInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -152,13 +152,6 @@ enum SpellRangeFlag
|
||||
SPELL_RANGE_RANGED = 2 //hunter range and ranged weapon
|
||||
};
|
||||
|
||||
enum SpellFinishReason : uint8
|
||||
{
|
||||
SPELL_FINISHED_SUCCESSFUL_CAST = 0, // spell has sucessfully launched
|
||||
SPELL_FINISHED_CANCELED = 1, // spell has been canceled (interrupts)
|
||||
SPELL_FINISHED_CHANNELING_COMPLETE = 2 // spell channeling has been finished
|
||||
};
|
||||
|
||||
struct SpellLogEffectPowerDrainParams
|
||||
{
|
||||
ObjectGuid Victim;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
@@ -247,11 +246,8 @@ struct boss_garothi_worldbreaker : public BossAI
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (reason != SPELL_FINISHED_SUCCESSFUL_CAST)
|
||||
return;
|
||||
|
||||
switch (spell->Id)
|
||||
{
|
||||
case SPELL_APOCALYPSE_DRIVE_FINAL_DAMAGE:
|
||||
|
||||
@@ -1322,9 +1322,9 @@ struct npc_shambling_horror_icc : public ScriptedAI
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
|
||||
void OnSpellFailed(SpellInfo const* spell) override
|
||||
{
|
||||
if (reason == SPELL_FINISHED_CANCELED && spell->Id == ENRAGE)
|
||||
if (spell->Id == ENRAGE)
|
||||
_events.RescheduleEvent(EVENT_ENRAGE, 1s);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "halls_of_stone.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
|
||||
@@ -83,9 +82,9 @@ struct boss_maiden_of_grief : public BossAI
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_SHOCK_OF_SORROW)
|
||||
if (spell->Id == SPELL_SHOCK_OF_SORROW)
|
||||
Talk(SAY_STUN);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
@@ -122,9 +121,9 @@ struct boss_exarch_maladaar : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_STOLEN_SOUL)
|
||||
if (spell->Id == SPELL_STOLEN_SOUL)
|
||||
if (roll_chance_i(25))
|
||||
Talk(SAY_SOUL_CLEAVE);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "the_botanica.h"
|
||||
@@ -97,9 +96,9 @@ struct boss_commander_sarannis : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_SUMMON_REINFORCEMENTS)
|
||||
if (spell->Id == SPELL_SUMMON_REINFORCEMENTS)
|
||||
Talk(SAY_SUMMON);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "the_botanica.h"
|
||||
|
||||
@@ -82,9 +81,9 @@ struct boss_warp_splinter : public BossAI
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void OnSpellCastFinished(SpellInfo const* spell, SpellFinishReason reason) override
|
||||
void OnSpellCast(SpellInfo const* spell) override
|
||||
{
|
||||
if (reason == SPELL_FINISHED_SUCCESSFUL_CAST && spell->Id == SPELL_SUMMON_SAPLINGS)
|
||||
if (spell->Id == SPELL_SUMMON_SAPLINGS)
|
||||
{
|
||||
for (uint32 summonSpells : SummonSaplingsSpells)
|
||||
DoCastSelf(summonSpells, true);
|
||||
|
||||
Reference in New Issue
Block a user