aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/CreatureAI.h14
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp15
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h9
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp14
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp14
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h15
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp2
-rw-r--r--src/server/game/Spells/Spell.cpp11
-rw-r--r--src/server/game/Spells/Spell.h7
9 files changed, 86 insertions, 15 deletions
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index 54b5d8c15af..041b27b6889 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -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; }
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index a6ac410475d..61d546ef17d 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -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);
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index be1ba853c4e..9f12e02af0c 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -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;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index ea30a829f9a..b7e78371973 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -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())
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 52e3f79e857..f2b793aff1e 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -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))
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 69dc73ea5ce..4908ac343e0 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -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
@@ -414,6 +417,13 @@ struct SmartEvent
struct
{
+ uint32 spell;
+ uint32 cooldownMin;
+ uint32 cooldownMax;
+ } spellCast;
+
+ struct
+ {
uint32 param1;
uint32 param2;
uint32 param3;
@@ -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
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index f3cbbcf7a42..4a5f8bedba5 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -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());
}
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 53656861b92..3f3b7cc9694 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -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;
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index bbe87563654..76cba756fd0 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -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;