summaryrefslogtreecommitdiff
path: root/src/scripts/Pet/pet_mage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/scripts/Pet/pet_mage.cpp')
-rw-r--r--src/scripts/Pet/pet_mage.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/scripts/Pet/pet_mage.cpp b/src/scripts/Pet/pet_mage.cpp
new file mode 100644
index 0000000000..4f2a32ceff
--- /dev/null
+++ b/src/scripts/Pet/pet_mage.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Ordered alphabetically using scriptname.
+ * Scriptnames of files in this file should be prefixed with "npc_pet_mag_".
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "CombatAI.h"
+#include "Pet.h"
+
+enum MageSpells
+{
+ SPELL_MAGE_CLONE_ME = 45204,
+ SPELL_MAGE_MASTERS_THREAT_LIST = 58838,
+ SPELL_PET_HIT_SCALING = 61013,
+ SPELL_SUMMON_MIRROR_IMAGE1 = 58831,
+ SPELL_SUMMON_MIRROR_IMAGE2 = 58833,
+ SPELL_SUMMON_MIRROR_IMAGE3 = 58834,
+ SPELL_SUMMON_MIRROR_IMAGE_GLYPH = 65047
+};
+
+class DeathEvent : public BasicEvent
+{
+ public:
+ DeathEvent(Creature& owner) : BasicEvent(), _owner(owner) { }
+
+ bool Execute(uint64 /*eventTime*/, uint32 /*diff*/)
+ {
+ Unit::Kill(&_owner, &_owner);
+ return true;
+ }
+
+ private:
+ Creature& _owner;
+};
+
+class npc_pet_mage_mirror_image : public CreatureScript
+{
+ public:
+ npc_pet_mage_mirror_image() : CreatureScript("npc_pet_mage_mirror_image") { }
+
+ struct npc_pet_mage_mirror_imageAI : CasterAI
+ {
+ npc_pet_mage_mirror_imageAI(Creature* creature) : CasterAI(creature) { }
+
+ uint32 selectionTimer;
+ uint64 _ebonGarogyleGUID;
+
+ void InitializeAI()
+ {
+ CasterAI::InitializeAI();
+ Unit* owner = me->GetOwner();
+ if (!owner)
+ return;
+
+ // Clone Me!
+ owner->CastSpell(me, SPELL_MAGE_CLONE_ME, true);
+
+ // xinef: Glyph of Mirror Image (4th copy)
+ float angle = 0.0f;
+ switch (me->GetUInt32Value(UNIT_CREATED_BY_SPELL))
+ {
+ case SPELL_SUMMON_MIRROR_IMAGE1:
+ angle = 0.5f * M_PI;
+ break;
+ case SPELL_SUMMON_MIRROR_IMAGE2:
+ angle = M_PI;
+ break;
+ case SPELL_SUMMON_MIRROR_IMAGE3:
+ angle = 1.5f * M_PI;
+ break;
+ }
+
+ ((Minion*)me)->SetFollowAngle(angle);
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
+ me->SetReactState(REACT_PASSIVE);
+
+ // Xinef: Inherit Master's Threat List (not yet implemented)
+ //owner->CastSpell((Unit*)NULL, SPELL_MAGE_MASTERS_THREAT_LIST, true);
+ HostileReference* ref = owner->getHostileRefManager().getFirst();
+ while (ref)
+ {
+ if (Unit* unit = ref->GetSource()->GetOwner())
+ unit->AddThreat(me, ref->getThreat() - ref->getTempThreatModifier());
+ ref = ref->next();
+ }
+
+ _ebonGarogyleGUID = 0;
+
+ // Xinef: copy caster auras
+ Unit::VisibleAuraMap const* visibleAuraMap = owner->GetVisibleAuras();
+ for (Unit::VisibleAuraMap::const_iterator itr = visibleAuraMap->begin(); itr != visibleAuraMap->end(); ++itr)
+ if (Aura* visAura = itr->second->GetBase())
+ {
+ // Ebon Gargoyle
+ if (visAura->GetId() == 49206 && me->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SPELL_SUMMON_MIRROR_IMAGE1)
+ {
+ if (Unit* garogyle = visAura->GetCaster())
+ _ebonGarogyleGUID = garogyle->GetGUID();
+ continue;
+ }
+ SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(visAura->GetId());
+ if (bounds.first != bounds.second)
+ continue;
+ std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(visAura->GetId() + SPELL_LINK_AURA);
+ if (!spellTriggered || !spellTriggered->empty())
+ continue;
+ if (Aura* newAura = me->AddAura(visAura->GetId(), me))
+ newAura->SetDuration(visAura->GetDuration());
+ }
+
+ me->m_Events.AddEvent(new DeathEvent(*me), me->m_Events.CalculateTime(29500));
+ }
+
+ // Do not reload Creature templates on evade mode enter - prevent visual lost
+ void EnterEvadeMode()
+ {
+ if (me->IsInEvadeMode() || !me->IsAlive())
+ return;
+
+ Unit* owner = me->GetCharmerOrOwner();
+
+ me->CombatStop(true);
+ if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
+ {
+ me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
+ }
+ }
+
+ bool MySelectNextTarget()
+ {
+ if (_ebonGarogyleGUID)
+ {
+ if (Unit* garogyle = ObjectAccessor::GetUnit(*me, _ebonGarogyleGUID))
+ garogyle->GetAI()->AttackStart(me);
+ _ebonGarogyleGUID = 0;
+ }
+ Unit* owner = me->GetOwner();
+ if (owner && owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ Unit* selection = owner->ToPlayer()->GetSelectedUnit();
+ if (selection && selection != me->GetVictim())
+ {
+ // target has cc, search target without cc!
+ if (selection->HasBreakableByDamageCrowdControlAura() || !me->IsValidAttackTarget(selection))
+ {
+ return false;
+ }
+
+ me->getThreatManager().resetAllAggro();
+ me->AddThreat(selection, 1000000.0f);
+ AttackStart(selection);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void Reset()
+ {
+ selectionTimer = 0;
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ events.Update(diff);
+ if (events.GetTimer() < 1200)
+ return;
+
+ if (!me->IsInCombat() || !me->GetVictim())
+ {
+ MySelectNextTarget();
+ return;
+ }
+
+ if (me->GetVictim()->HasBreakableByDamageCrowdControlAura() || !me->GetVictim()->IsAlive())
+ {
+ me->InterruptNonMeleeSpells(false);
+ if (!MySelectNextTarget())
+ EnterEvadeMode();
+ return;
+ }
+
+ selectionTimer += diff;
+ if (selectionTimer >= 1000)
+ {
+ MySelectNextTarget();
+ selectionTimer = 0;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ if (uint32 spellId = events.GetEvent())
+ {
+ events.RescheduleEvent(spellId, spellId == 59637 ? 6500 : 2500);
+ me->CastSpell(me->GetVictim(), spellId, false);
+ }
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_pet_mage_mirror_imageAI(creature);
+ }
+};
+
+void AddSC_mage_pet_scripts()
+{
+ new npc_pet_mage_mirror_image();
+}