mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 10:26:28 +01:00
*Add SpellCasterAI as a framework for casting only units (like ebon gargoyle or mirror image.
--HG-- branch : trunk
This commit is contained in:
@@ -1639,12 +1639,13 @@ CreatureAI* GetAI_mob_mojo(Creature *_Creature)
|
||||
return new mob_mojoAI (_Creature);
|
||||
}
|
||||
|
||||
struct TRINITY_DLL_DECL npc_mirror_image : SpellAI
|
||||
struct TRINITY_DLL_DECL npc_mirror_image : SpellCasterAI
|
||||
{
|
||||
npc_mirror_image(Creature *c) : SpellAI(c) {Reset();}
|
||||
npc_mirror_image(Creature *c) : SpellCasterAI(c) {}
|
||||
|
||||
void Reset()
|
||||
void InitializeAI()
|
||||
{
|
||||
SpellCasterAI::InitializeAI();
|
||||
Unit * owner = me->GetOwner();
|
||||
if (!owner)
|
||||
return;
|
||||
@@ -1656,43 +1657,7 @@ struct TRINITY_DLL_DECL npc_mirror_image : SpellAI
|
||||
owner->CastSpell(me, 45204, false);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit *who)
|
||||
{
|
||||
if (spells.empty())
|
||||
return;
|
||||
|
||||
uint32 spell = rand() % spells.size();
|
||||
uint32 count = 0;
|
||||
for(SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count)
|
||||
{
|
||||
uint32 cooldown = GetAISpellInfo(*itr)->cooldown;
|
||||
if (count == spell)
|
||||
{
|
||||
DoCast(spells[spell]);
|
||||
cooldown += me->GetCurrentSpellCastTime(*itr);
|
||||
}
|
||||
events.ScheduleEvent(*itr, cooldown);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if(me->hasUnitState(UNIT_STAT_CASTING))
|
||||
return;
|
||||
|
||||
if(uint32 spellId = events.ExecuteEvent())
|
||||
{
|
||||
DoCast(spellId);
|
||||
uint32 casttime = me->GetCurrentSpellCastTime(spellId);
|
||||
events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->cooldown);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not reload creature templates on evade mode enter - prevent visual lost
|
||||
void EnterEvadeMode()
|
||||
{
|
||||
if(me->IsInEvadeMode() || !me->isAlive())
|
||||
@@ -1707,7 +1672,6 @@ struct TRINITY_DLL_DECL npc_mirror_image : SpellAI
|
||||
me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, m_creature->GetFollowAngle(), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_npc_mirror_image(Creature *_Creature)
|
||||
|
||||
@@ -91,3 +91,58 @@ void SpellAI::UpdateAI(const uint32 diff)
|
||||
else
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void SpellCasterAI::InitializeAI()
|
||||
{
|
||||
SpellAI::InitializeAI();
|
||||
float m_attackDist = 30.0f;
|
||||
for(SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr)
|
||||
{
|
||||
if (AISpellInfo[*itr].condition == AICOND_COMBAT && m_attackDist > GetAISpellInfo(*itr)->maxRange)
|
||||
m_attackDist = GetAISpellInfo(*itr)->maxRange;
|
||||
}
|
||||
if (m_attackDist == 30.0f)
|
||||
m_attackDist = MELEE_RANGE;
|
||||
}
|
||||
|
||||
void SpellCasterAI::EnterCombat(Unit *who)
|
||||
{
|
||||
if (spells.empty())
|
||||
return;
|
||||
|
||||
uint32 spell = rand() % spells.size();
|
||||
uint32 count = 0;
|
||||
for(SpellVct::iterator itr = spells.begin(); itr != spells.end(); ++itr, ++count)
|
||||
{
|
||||
if(AISpellInfo[*itr].condition == AICOND_AGGRO)
|
||||
me->CastSpell(who, *itr, false);
|
||||
else if (AISpellInfo[*itr].condition == AICOND_COMBAT)
|
||||
{
|
||||
uint32 cooldown = GetAISpellInfo(*itr)->realCooldown;
|
||||
if (count == spell)
|
||||
{
|
||||
DoCast(spells[spell]);
|
||||
cooldown += me->GetCurrentSpellCastTime(*itr);
|
||||
}
|
||||
events.ScheduleEvent(*itr, cooldown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellCasterAI::UpdateAI(const uint32 diff)
|
||||
{
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if(me->hasUnitState(UNIT_STAT_CASTING))
|
||||
return;
|
||||
|
||||
if(uint32 spellId = events.ExecuteEvent())
|
||||
{
|
||||
DoCast(spellId);
|
||||
uint32 casttime = me->GetCurrentSpellCastTime(spellId);
|
||||
events.ScheduleEvent(spellId, (casttime ? casttime : 500) + GetAISpellInfo(spellId)->realCooldown);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,4 +53,16 @@ class TRINITY_DLL_SPEC SpellAI : public CreatureAI
|
||||
SpellVct spells;
|
||||
};
|
||||
|
||||
class TRINITY_DLL_SPEC SpellCasterAI : public SpellAI
|
||||
{
|
||||
public:
|
||||
explicit SpellCasterAI(Creature *c) : SpellAI(c) {m_attackDist = MELEE_RANGE;}
|
||||
void InitializeAI();
|
||||
void AttackStart(Unit * victim){SpellAI::AttackStartCaster(victim, m_attackDist);}
|
||||
void UpdateAI(const uint32 diff);
|
||||
void EnterCombat(Unit *who);
|
||||
private:
|
||||
float m_attackDist;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -246,10 +246,13 @@ enum AICondition
|
||||
|
||||
struct AISpellInfoType
|
||||
{
|
||||
AISpellInfoType() : target(AITARGET_SELF), condition(AICOND_COMBAT), cooldown(AI_DEFAULT_COOLDOWN) {}
|
||||
AISpellInfoType() : target(AITARGET_SELF), condition(AICOND_COMBAT)
|
||||
, cooldown(AI_DEFAULT_COOLDOWN), realCooldown(0), maxRange(0.0f){}
|
||||
AITarget target;
|
||||
AICondition condition;
|
||||
uint32 cooldown;
|
||||
uint32 realCooldown;
|
||||
float maxRange;
|
||||
};
|
||||
|
||||
TRINITY_DLL_SPEC AISpellInfoType * GetAISpellInfo(uint32 i);
|
||||
|
||||
@@ -542,7 +542,6 @@ Map::Add(T *obj)
|
||||
//also, trigger needs to cast spell, if not update, cannot see visual
|
||||
//if(obj->GetTypeId() != TYPEID_UNIT)
|
||||
UpdateObjectVisibility(obj,cell,p);
|
||||
|
||||
AddNotifier(obj);
|
||||
}
|
||||
|
||||
|
||||
@@ -6856,7 +6856,6 @@ void Spell::SummonGuardian(uint32 entry, SummonPropertiesEntry const *properties
|
||||
TempSummon *summon = map->SummonCreature(entry, px, py, pz, m_caster->GetOrientation(), properties, duration, caster);
|
||||
if(!summon)
|
||||
return;
|
||||
|
||||
if(summon->HasSummonMask(SUMMON_MASK_GUARDIAN))
|
||||
((Guardian*)summon)->InitStatsForLevel(level);
|
||||
|
||||
|
||||
@@ -11491,10 +11491,6 @@ Unit* Creature::SelectVictim()
|
||||
//next-victim-selection algorithm and evade mode are called
|
||||
//threat list sorting etc.
|
||||
|
||||
//This should not be called by unit who does not have a threatlist
|
||||
//or who does not have threat (totem/pet/critter)
|
||||
//otherwise enterevademode every update
|
||||
|
||||
Unit* target = NULL;
|
||||
// First checking if we have some taunt on us
|
||||
const AuraEffectList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT);
|
||||
|
||||
@@ -325,6 +325,10 @@ void UnitAI::FillAISpellInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
AIInfo->realCooldown = spellInfo->RecoveryTime + spellInfo->StartRecoveryTime;
|
||||
SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex);
|
||||
if (srange)
|
||||
AIInfo->maxRange = srange->maxRangeHostile * 3 / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user