diff options
Diffstat (limited to 'src/scripts/Pet/pet_mage.cpp')
-rw-r--r-- | src/scripts/Pet/pet_mage.cpp | 229 |
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(); +} |