diff options
-rw-r--r-- | src/server/scripts/Pet/pet_mage.cpp | 267 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_priest.cpp | 72 | ||||
-rw-r--r-- | src/server/scripts/Pet/pet_shaman.cpp | 148 |
3 files changed, 216 insertions, 271 deletions
diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index d1cedaa0e69..06797c4a155 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -42,169 +42,158 @@ enum MirrorImageTimers TIMER_MIRROR_IMAGE_FIRE_BLAST = 6500 }; -class npc_pet_mage_mirror_image : public CreatureScript +struct npc_pet_mage_mirror_image : ScriptedAI { - public: - npc_pet_mage_mirror_image() : CreatureScript("npc_pet_mage_mirror_image") { } - - struct npc_pet_mage_mirror_imageAI : ScriptedAI + const float CHASE_DISTANCE = 35.0f; + + npc_pet_mage_mirror_image(Creature* creature) : ScriptedAI(creature) { } + + void InitializeAI() override + { + Unit* owner = me->GetOwner(); + if (!owner) + return; + + // here mirror image casts on summoner spell (not present in client dbc) 49866 + // here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcast by mirror images (stats related?) + // Clone Me! + owner->CastSpell(me, SPELL_MAGE_CLONE_ME, true); + } + + // custom UpdateVictim implementation to handle special target selection + // we prioritize between things that are in combat with owner based on the owner's threat to them + bool UpdateVictim() + { + Unit* owner = me->GetOwner(); + if (!owner) + return false; + + if (!me->HasUnitState(UNIT_STATE_CASTING) && !me->IsInCombat() && !owner->IsInCombat()) + return false; + + Unit* currentTarget = me->GetVictim(); + if (currentTarget && !CanAIAttack(currentTarget)) { - const float CHASE_DISTANCE = 35.0f; - - npc_pet_mage_mirror_imageAI(Creature* creature) : ScriptedAI(creature) { } + me->InterruptNonMeleeSpells(true); // do not finish casting on invalid targets + me->AttackStop(); + currentTarget = nullptr; + } - void InitializeAI() override - { - Unit* owner = me->GetOwner(); - if (!owner) - return; - - // here mirror image casts on summoner spell (not present in client dbc) 49866 - // here should be auras (not present in client dbc): 35657, 35658, 35659, 35660 selfcast by mirror images (stats related?) - // Clone Me! - owner->CastSpell(me, SPELL_MAGE_CLONE_ME, true); - } + // don't reselect if we're currently casting anyway + if (currentTarget && me->HasUnitState(UNIT_STATE_CASTING)) + return true; - // custom UpdateVictim implementation to handle special target selection - // we prioritize between things that are in combat with owner based on the owner's threat to them - bool UpdateVictim() + Unit* selectedTarget = nullptr; + CombatManager const& mgr = owner->GetCombatManager(); + if (mgr.HasPvPCombat()) + { // select pvp target + float minDistance = 0.0f; + for (auto const& pair : mgr.GetPvPCombatRefs()) { - Unit* owner = me->GetOwner(); - if (!owner) - return false; - - if (!me->HasUnitState(UNIT_STATE_CASTING) && !me->IsInCombat() && !owner->IsInCombat()) - return false; - - Unit* currentTarget = me->GetVictim(); - if (currentTarget && !CanAIAttack(currentTarget)) - { - me->InterruptNonMeleeSpells(true); // do not finish casting on invalid targets - me->AttackStop(); - currentTarget = nullptr; - } - - // don't reselect if we're currently casting anyway - if (currentTarget && me->HasUnitState(UNIT_STATE_CASTING)) - return true; - - Unit* selectedTarget = nullptr; - CombatManager const& mgr = owner->GetCombatManager(); - if (mgr.HasPvPCombat()) - { // select pvp target - float minDistance = 0.0f; - for (auto const& pair : mgr.GetPvPCombatRefs()) - { - Unit* target = pair.second->GetOther(owner); - if (target->GetTypeId() != TYPEID_PLAYER) - continue; - if (!CanAIAttack(target)) - continue; - - float dist = owner->GetDistance(target); - if (!selectedTarget || dist < minDistance) - { - selectedTarget = target; - minDistance = dist; - } - } - } - - if (!selectedTarget) - { // select pve target - float maxThreat = 0.0f; - for (auto const& pair : mgr.GetPvECombatRefs()) - { - Unit* target = pair.second->GetOther(owner); - if (!CanAIAttack(target)) - continue; - - float threat = target->GetThreatManager().GetThreat(owner); - if (threat >= maxThreat) - { - selectedTarget = target; - maxThreat = threat; - } - } - } - - if (!selectedTarget) + Unit* target = pair.second->GetOther(owner); + if (target->GetTypeId() != TYPEID_PLAYER) + continue; + if (!CanAIAttack(target)) + continue; + + float dist = owner->GetDistance(target); + if (!selectedTarget || dist < minDistance) { - EnterEvadeMode(EVADE_REASON_NO_HOSTILES); - return false; + selectedTarget = target; + minDistance = dist; } - - if (selectedTarget != me->GetVictim()) - AttackStartCaster(selectedTarget, CHASE_DISTANCE); - return true; } + } - void UpdateAI(uint32 diff) override + if (!selectedTarget) + { // select pve target + float maxThreat = 0.0f; + for (auto const& pair : mgr.GetPvECombatRefs()) { - Unit* owner = me->GetOwner(); - if (!owner) - { - me->DespawnOrUnsummon(); - return; - } - - if (_fireBlastTimer) - { - if (_fireBlastTimer <= diff) - _fireBlastTimer = 0; - else - _fireBlastTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + Unit* target = pair.second->GetOther(owner); + if (!CanAIAttack(target)) + continue; - if (!_fireBlastTimer) + float threat = target->GetThreatManager().GetThreat(owner); + if (threat >= maxThreat) { - DoCastVictim(SPELL_MAGE_FIRE_BLAST); - _fireBlastTimer = TIMER_MIRROR_IMAGE_FIRE_BLAST; + selectedTarget = target; + maxThreat = threat; } - else - DoCastVictim(SPELL_MAGE_FROST_BOLT); } + } - bool CanAIAttack(Unit const* who) const override - { - Unit* owner = me->GetOwner(); - return owner && who->IsAlive() && me->IsValidAttackTarget(who) && - !who->HasBreakableByDamageCrowdControlAura() && - who->IsInCombatWith(owner) && ScriptedAI::CanAIAttack(who); - } + if (!selectedTarget) + { + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); + return false; + } - // Do not reload Creature templates on evade mode enter - prevent visual lost - void EnterEvadeMode(EvadeReason /*why*/) override - { - if (me->IsInEvadeMode() || !me->IsAlive()) - return; + if (selectedTarget != me->GetVictim()) + AttackStartCaster(selectedTarget, CHASE_DISTANCE); + return true; + } + + void UpdateAI(uint32 diff) override + { + Unit* owner = me->GetOwner(); + if (!owner) + { + me->DespawnOrUnsummon(); + return; + } - Unit* owner = me->GetCharmerOrOwner(); + if (_fireBlastTimer) + { + if (_fireBlastTimer <= diff) + _fireBlastTimer = 0; + else + _fireBlastTimer -= diff; + } - me->CombatStop(true); - if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); - } - } + if (!UpdateVictim()) + return; - uint32 _fireBlastTimer = 0; - }; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - CreatureAI* GetAI(Creature* creature) const override + if (!_fireBlastTimer) { - return new npc_pet_mage_mirror_imageAI(creature); + DoCastVictim(SPELL_MAGE_FIRE_BLAST); + _fireBlastTimer = TIMER_MIRROR_IMAGE_FIRE_BLAST; } + else + DoCastVictim(SPELL_MAGE_FROST_BOLT); + } + + bool CanAIAttack(Unit const* who) const override + { + Unit* owner = me->GetOwner(); + return owner && who->IsAlive() && me->IsValidAttackTarget(who) && + !who->HasBreakableByDamageCrowdControlAura() && + who->IsInCombatWith(owner) && ScriptedAI::CanAIAttack(who); + } + + // Do not reload Creature templates on evade mode enter - prevent visual lost + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (me->IsInEvadeMode() || !me->IsAlive()) + return; + + Unit* owner = me->GetCharmerOrOwner(); + + me->CombatStop(true); + if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW)) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); + } + } + + uint32 _fireBlastTimer = 0; }; void AddSC_mage_pet_scripts() { - new npc_pet_mage_mirror_image(); + RegisterCreatureAI(npc_pet_mage_mirror_image); } diff --git a/src/server/scripts/Pet/pet_priest.cpp b/src/server/scripts/Pet/pet_priest.cpp index f9990f27e7e..2754a5b077a 100644 --- a/src/server/scripts/Pet/pet_priest.cpp +++ b/src/server/scripts/Pet/pet_priest.cpp @@ -32,63 +32,41 @@ enum PriestSpells SPELL_PRIEST_LIGHTWELL_CHARGES = 59907 }; -class npc_pet_pri_lightwell : public CreatureScript +struct npc_pet_pri_lightwell : public PassiveAI { - public: - npc_pet_pri_lightwell() : CreatureScript("npc_pet_pri_lightwell") { } + npc_pet_pri_lightwell(Creature* creature) : PassiveAI(creature) + { + DoCast(me, SPELL_PRIEST_LIGHTWELL_CHARGES, false); + } - struct npc_pet_pri_lightwellAI : public PassiveAI - { - npc_pet_pri_lightwellAI(Creature* creature) : PassiveAI(creature) - { - DoCast(me, SPELL_PRIEST_LIGHTWELL_CHARGES, false); - } + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (!me->IsAlive()) + return; - void EnterEvadeMode(EvadeReason /*why*/) override - { - if (!me->IsAlive()) - return; - - me->CombatStop(true); - EngagementOver(); - me->ResetPlayerDamageReq(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pet_pri_lightwellAI(creature); - } + me->CombatStop(true); + EngagementOver(); + me->ResetPlayerDamageReq(); + } }; -class npc_pet_pri_shadowfiend : public CreatureScript +struct npc_pet_pri_shadowfiend : public PetAI { - public: - npc_pet_pri_shadowfiend() : CreatureScript("npc_pet_pri_shadowfiend") { } - - struct npc_pet_pri_shadowfiendAI : public PetAI - { - npc_pet_pri_shadowfiendAI(Creature* creature) : PetAI(creature) { } - - void IsSummonedBy(WorldObject* summonerWO) override - { - Unit* summoner = summonerWO->ToUnit(); - if (!summoner) - return; + npc_pet_pri_shadowfiend(Creature* creature) : PetAI(creature) { } - if (summoner->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOWFIEND)) - DoCastAOE(SPELL_PRIEST_SHADOWFIEND_DEATH); - } - }; + void IsSummonedBy(WorldObject* summonerWO) override + { + Unit* summoner = summonerWO->ToUnit(); + if (!summoner) + return; - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pet_pri_shadowfiendAI(creature); - } + if (summoner->HasAura(SPELL_PRIEST_GLYPH_OF_SHADOWFIEND)) + DoCastAOE(SPELL_PRIEST_SHADOWFIEND_DEATH); + } }; void AddSC_priest_pet_scripts() { - new npc_pet_pri_lightwell(); - new npc_pet_pri_shadowfiend(); + RegisterCreatureAI(npc_pet_pri_lightwell); + RegisterCreatureAI(npc_pet_pri_shadowfiend); } diff --git a/src/server/scripts/Pet/pet_shaman.cpp b/src/server/scripts/Pet/pet_shaman.cpp index 1a20470d75d..bb86bb2cc20 100644 --- a/src/server/scripts/Pet/pet_shaman.cpp +++ b/src/server/scripts/Pet/pet_shaman.cpp @@ -41,110 +41,88 @@ enum ShamanEvents EVENT_SHAMAN_FIREBLAST = 3 }; -class npc_pet_shaman_earth_elemental : public CreatureScript +struct npc_pet_shaman_earth_elemental : public ScriptedAI { - public: - npc_pet_shaman_earth_elemental() : CreatureScript("npc_pet_shaman_earth_elemental") { } + npc_pet_shaman_earth_elemental(Creature* creature) : ScriptedAI(creature) { } - struct npc_pet_shaman_earth_elementalAI : public ScriptedAI - { - npc_pet_shaman_earth_elementalAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_SHAMAN_ANGEREDEARTH, 0s); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_SHAMAN_ANGEREDEARTH, 0s); + } - if (_events.ExecuteEvent() == EVENT_SHAMAN_ANGEREDEARTH) - { - DoCastVictim(SPELL_SHAMAN_ANGEREDEARTH); - _events.ScheduleEvent(EVENT_SHAMAN_ANGEREDEARTH, 5s, 20s); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - DoMeleeAttackIfReady(); - } + _events.Update(diff); - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override + if (_events.ExecuteEvent() == EVENT_SHAMAN_ANGEREDEARTH) { - return new npc_pet_shaman_earth_elementalAI(creature); + DoCastVictim(SPELL_SHAMAN_ANGEREDEARTH); + _events.ScheduleEvent(EVENT_SHAMAN_ANGEREDEARTH, 5s, 20s); } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; }; -class npc_pet_shaman_fire_elemental : public CreatureScript +struct npc_pet_shaman_fire_elemental : public ScriptedAI { - public: - npc_pet_shaman_fire_elemental() : CreatureScript("npc_pet_shaman_fire_elemental") { } + npc_pet_shaman_fire_elemental(Creature* creature) : ScriptedAI(creature) { } - struct npc_pet_shaman_fire_elementalAI : public ScriptedAI - { - npc_pet_shaman_fire_elementalAI(Creature* creature) : ScriptedAI(creature) { } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_SHAMAN_FIRENOVA, 5s, 20s); + _events.ScheduleEvent(EVENT_SHAMAN_FIREBLAST, 5s, 20s); + _events.ScheduleEvent(EVENT_SHAMAN_FIRESHIELD, 0s); + } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_SHAMAN_FIRENOVA, 5s, 20s); - _events.ScheduleEvent(EVENT_SHAMAN_FIREBLAST, 5s, 20s); - _events.ScheduleEvent(EVENT_SHAMAN_FIRESHIELD, 0s); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SHAMAN_FIRENOVA: - DoCastVictim(SPELL_SHAMAN_FIRENOVA); - _events.ScheduleEvent(EVENT_SHAMAN_FIRENOVA, 5s, 20s); - break; - case EVENT_SHAMAN_FIRESHIELD: - DoCastVictim(SPELL_SHAMAN_FIRESHIELD); - _events.ScheduleEvent(EVENT_SHAMAN_FIRESHIELD, 2s); - break; - case EVENT_SHAMAN_FIREBLAST: - DoCastVictim(SPELL_SHAMAN_FIREBLAST); - _events.ScheduleEvent(EVENT_SHAMAN_FIREBLAST, 5s, 20s); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - private: - EventMap _events; - }; + _events.Update(diff); - CreatureAI* GetAI(Creature* creature) const override + while (uint32 eventId = _events.ExecuteEvent()) { - return new npc_pet_shaman_fire_elementalAI(creature); + switch (eventId) + { + case EVENT_SHAMAN_FIRENOVA: + DoCastVictim(SPELL_SHAMAN_FIRENOVA); + _events.ScheduleEvent(EVENT_SHAMAN_FIRENOVA, 5s, 20s); + break; + case EVENT_SHAMAN_FIRESHIELD: + DoCastVictim(SPELL_SHAMAN_FIRESHIELD); + _events.ScheduleEvent(EVENT_SHAMAN_FIRESHIELD, 2s); + break; + case EVENT_SHAMAN_FIREBLAST: + DoCastVictim(SPELL_SHAMAN_FIREBLAST); + _events.ScheduleEvent(EVENT_SHAMAN_FIREBLAST, 5s, 20s); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; }; void AddSC_shaman_pet_scripts() { - new npc_pet_shaman_earth_elemental(); - new npc_pet_shaman_fire_elemental(); + RegisterCreatureAI(npc_pet_shaman_earth_elemental); + RegisterCreatureAI(npc_pet_shaman_fire_elemental); } |