mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 19:37:02 +00:00
[9062] Implement two helper-functions for casting spell in creatureAI.
Function will return a cast result, with fail reasons if spell can not be casted (can be used to take alternative action). Please note this is not a full list of cast fail errors/reasons, but will cover a few basic errors that may occur. The virtual function CanCastSpell() may be adjusted for custom needs from script library if not the default is sufficient. Signed-off-by: NoFantasy <nofantasy@nf.no>
This commit is contained in:
parent
67dd48e2d4
commit
f4c6cf7337
3 changed files with 104 additions and 1 deletions
|
|
@ -28,3 +28,90 @@ void CreatureAI::AttackedBy( Unit* attacker )
|
||||||
if(!m_creature->getVictim())
|
if(!m_creature->getVictim())
|
||||||
AttackStart(attacker);
|
AttackStart(attacker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered)
|
||||||
|
{
|
||||||
|
// If not triggered, we check
|
||||||
|
if (!isTriggered)
|
||||||
|
{
|
||||||
|
// State does not allow
|
||||||
|
if (m_creature->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DIED))
|
||||||
|
return CAST_FAIL_STATE;
|
||||||
|
|
||||||
|
if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
|
||||||
|
return CAST_FAIL_STATE;
|
||||||
|
|
||||||
|
if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
|
||||||
|
return CAST_FAIL_STATE;
|
||||||
|
|
||||||
|
// Check for power (also done by Spell::CheckCast())
|
||||||
|
if (m_creature->GetPower((Powers)pSpell->powerType) < pSpell->manaCost)
|
||||||
|
return CAST_FAIL_POWER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const SpellRangeEntry *pSpellRange = sSpellRangeStore.LookupEntry(pSpell->rangeIndex))
|
||||||
|
{
|
||||||
|
if (pTarget != m_creature)
|
||||||
|
{
|
||||||
|
// pTarget is out of range of this spell (also done by Spell::CheckCast())
|
||||||
|
float fDistance = m_creature->GetCombatDistance(pTarget);
|
||||||
|
|
||||||
|
if (fDistance > (m_creature->IsHostileTo(pTarget) ? pSpellRange->maxRange : pSpellRange->maxRangeFriendly))
|
||||||
|
return CAST_FAIL_TOO_FAR;
|
||||||
|
|
||||||
|
float fMinRange = m_creature->IsHostileTo(pTarget) ? pSpellRange->minRange : pSpellRange->minRangeFriendly;
|
||||||
|
|
||||||
|
if (fMinRange && fDistance < fMinRange)
|
||||||
|
return CAST_FAIL_TOO_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CAST_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return CAST_FAIL_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint64 uiOriginalCasterGUID)
|
||||||
|
{
|
||||||
|
Unit* pCaster = m_creature;
|
||||||
|
|
||||||
|
if (uiCastFlags & CAST_FORCE_TARGET_SELF)
|
||||||
|
pCaster = pTarget;
|
||||||
|
|
||||||
|
// Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
|
||||||
|
if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS)))
|
||||||
|
{
|
||||||
|
if (const SpellEntry* pSpell = sSpellStore.LookupEntry(uiSpell))
|
||||||
|
{
|
||||||
|
// If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
|
||||||
|
if (uiCastFlags & CAST_AURA_NOT_PRESENT)
|
||||||
|
{
|
||||||
|
if (pTarget->HasAura(uiSpell))
|
||||||
|
return CAST_FAIL_TARGET_AURA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if cannot cast spell
|
||||||
|
if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
|
||||||
|
{
|
||||||
|
CanCastResult castResult = CanCastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED);
|
||||||
|
|
||||||
|
if (castResult != CAST_OK)
|
||||||
|
return castResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interrupt any previous spell
|
||||||
|
if (uiCastFlags & CAST_INTURRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false))
|
||||||
|
pCaster->InterruptNonMeleeSpells(false);
|
||||||
|
|
||||||
|
pCaster->CastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED, NULL, NULL, uiOriginalCasterGUID);
|
||||||
|
return CAST_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", m_creature->GetEntry(), uiSpell);
|
||||||
|
return CAST_FAIL_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return CAST_FAIL_IS_CASTING;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,18 @@ struct SpellEntry;
|
||||||
#define TIME_INTERVAL_LOOK 5000
|
#define TIME_INTERVAL_LOOK 5000
|
||||||
#define VISIBILITY_RANGE 10000
|
#define VISIBILITY_RANGE 10000
|
||||||
|
|
||||||
|
enum CanCastResult
|
||||||
|
{
|
||||||
|
CAST_OK = 0,
|
||||||
|
CAST_FAIL_IS_CASTING = 1,
|
||||||
|
CAST_FAIL_OTHER = 2,
|
||||||
|
CAST_FAIL_TOO_FAR = 3,
|
||||||
|
CAST_FAIL_TOO_CLOSE = 4,
|
||||||
|
CAST_FAIL_POWER = 5,
|
||||||
|
CAST_FAIL_STATE = 6,
|
||||||
|
CAST_FAIL_TARGET_AURA = 7
|
||||||
|
};
|
||||||
|
|
||||||
enum CastFlags
|
enum CastFlags
|
||||||
{
|
{
|
||||||
CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
|
CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
|
||||||
|
|
@ -68,6 +80,10 @@ class MANGOS_DLL_SPEC CreatureAI
|
||||||
// Called at any heal cast/item used (call non implemented)
|
// Called at any heal cast/item used (call non implemented)
|
||||||
virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {}
|
virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {}
|
||||||
|
|
||||||
|
// Helper functions for cast spell
|
||||||
|
CanCastResult DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags = 0, uint64 uiOriginalCasterGUID = 0);
|
||||||
|
virtual CanCastResult CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered);
|
||||||
|
|
||||||
// Called at any Damage to any victim (before damage apply)
|
// Called at any Damage to any victim (before damage apply)
|
||||||
virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {}
|
virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "9061"
|
#define REVISION_NR "9062"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue