diff options
author | jackpoz <giacomopoz@gmail.com> | 2015-12-12 17:43:35 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-03-21 19:04:39 +0100 |
commit | 96ca739a0b0d2b34a28fbac0593e076fb3c42f1b (patch) | |
tree | d4e30a77a337a6e25949e5285e6ef56ed7db9ce8 /src | |
parent | d14de3533544eb0bfeb68f4ed3775a5062161f12 (diff) |
Merge pull request #14896 from Ofinka/dupl
(cherry picked from commit 263f127d075d56be8fd19ef36871bf245bc4bdcc)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Pet/pet_mage.cpp | 181 |
1 files changed, 178 insertions, 3 deletions
diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index 274fa27c9d0..525f321509e 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -24,11 +24,21 @@ #include "ScriptedCreature.h" #include "CombatAI.h" #include "Pet.h" +#include "PetAI.h" enum MageSpells { SPELL_MAGE_CLONE_ME = 45204, - SPELL_MAGE_MASTERS_THREAT_LIST = 58838 + SPELL_MAGE_MASTERS_THREAT_LIST = 58838, + SPELL_MAGE_FROST_BOLT = 59638, + SPELL_MAGE_FIRE_BLAST = 59637 +}; + +enum MirrorImageTimers +{ + TIMER_MIRROR_IMAGE_INIT = 0, + TIMER_MIRROR_IMAGE_FROST_BOLT = 4000, + TIMER_MIRROR_IMAGE_FIRE_BLAST = 6000 }; class npc_pet_mage_mirror_image : public CreatureScript @@ -40,20 +50,184 @@ class npc_pet_mage_mirror_image : public CreatureScript { npc_pet_mage_mirror_imageAI(Creature* creature) : CasterAI(creature) { } + void Init() + { + Unit* owner = me->GetCharmerOrOwner(); + + std::list<Unit*> targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); + me->VisitNearbyObject(40.0f, searcher); + + Unit* highestThreatUnit = nullptr; + float highestThreat = 0.0f; + Unit* nearestPlayer = nullptr; + for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) + { + // Consider only units without CC + if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) + { + // Take first found unit + if (!highestThreatUnit && (*iter)->GetTypeId() != TYPEID_PLAYER) + { + highestThreatUnit = (*iter); + continue; + } + if (!nearestPlayer && ((*iter)->GetTypeId() == TYPEID_PLAYER)) + { + nearestPlayer = (*iter); + continue; + } + // else compare best fit unit with current unit + ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); + for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) + { + // Try to find threat referenced to owner + if ((*trig_citr)->getTarget() == owner) + { + // Check if best fit hostile unit hs lower threat than this current unit + if (highestThreat < (*trig_citr)->getThreat()) + { + // If so, update best fit unit + highestThreat = (*trig_citr)->getThreat(); + highestThreatUnit = (*iter); + break; + } + } + } + // In case no unit with threat was found so far, always check for nearest unit (only for players) + if ((*iter)->GetTypeId() == TYPEID_PLAYER) + { + // If this player is closer than the previous one, update it + if (me->GetDistance((*iter)->GetPosition()) < me->GetDistance(nearestPlayer->GetPosition())) + nearestPlayer = (*iter); + } + } + } + // Prioritize units with threat referenced to owner + if (highestThreat > 0.0f && highestThreatUnit) + me->Attack(highestThreatUnit, false); + // If there is no such target, try to attack nearest hostile unit if such exists + else if (nearestPlayer) + me->Attack(nearestPlayer, false); + } + + bool IsInThreatList(Unit* target) + { + Unit* owner = me->GetCharmerOrOwner(); + + std::list<Unit*> targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); + me->VisitNearbyObject(40.0f, searcher); + + for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) + { + if ((*iter) == target) + { + // Consider only units without CC + if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) + { + ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); + for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) + { + // Try to find threat referenced to owner + if ((*trig_citr)->getTarget() == owner) + return true; + } + } + } + } + return false; + } + void InitializeAI() override { CasterAI::InitializeAI(); Unit* owner = me->GetOwner(); if (!owner) return; - // Inherit Master's Threat List (not yet implemented) - owner->CastSpell((Unit*)NULL, SPELL_MAGE_MASTERS_THREAT_LIST, true); + // 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, false); } + void EnterCombat(Unit* who) override + { + if (me->GetVictim() && !me->GetVictim()->HasBreakableByDamageCrowdControlAura(me)) + { + me->CastSpell(who, SPELL_MAGE_FIRE_BLAST, false); + events.ScheduleEvent(SPELL_MAGE_FROST_BOLT, TIMER_MIRROR_IMAGE_INIT); + events.ScheduleEvent(SPELL_MAGE_FIRE_BLAST, TIMER_MIRROR_IMAGE_FIRE_BLAST); + } + else + EnterEvadeMode(); + } + + void Reset() override + { + events.Reset(); + } + + void UpdateAI(uint32 diff) override + { + Unit* owner = me->GetCharmerOrOwner(); + Unit* target = owner->getAttackerForHelper(); + + events.Update(diff); + + // prevent CC interrupts by images + if (me->GetVictim() && me->EnsureVictim()->HasBreakableByDamageCrowdControlAura(me)) + { + me->InterruptNonMeleeSpells(false); + return; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + if (!owner) + return; + + // assign target if image doesnt have any or the target is not actual + if (!target || me->GetVictim() != target) + { + Unit* ownerTarget = nullptr; + if (Player* owner = me->GetCharmerOrOwner()->ToPlayer()) + ownerTarget = owner->GetSelectedUnit(); + + // recognize which victim will be choosen + if (ownerTarget && ownerTarget->GetTypeId() == TYPEID_PLAYER) + { + if (!ownerTarget->HasBreakableByDamageCrowdControlAura(ownerTarget)) + me->Attack(ownerTarget, false); + } + else if (ownerTarget && (ownerTarget->GetTypeId() != TYPEID_PLAYER) && IsInThreatList(ownerTarget)) + { + if (!ownerTarget->HasBreakableByDamageCrowdControlAura(ownerTarget)) + me->Attack(ownerTarget, false); + } + else + Init(); + } + + if (uint32 spellId = events.ExecuteEvent()) + { + if (spellId == SPELL_MAGE_FROST_BOLT) + { + events.ScheduleEvent(SPELL_MAGE_FROST_BOLT, TIMER_MIRROR_IMAGE_FROST_BOLT); + DoCastVictim(spellId); + } + else if (spellId == SPELL_MAGE_FIRE_BLAST) + { + DoCastVictim(spellId); + events.ScheduleEvent(SPELL_MAGE_FIRE_BLAST, TIMER_MIRROR_IMAGE_FIRE_BLAST); + } + } + } + // Do not reload Creature templates on evade mode enter - prevent visual lost void EnterEvadeMode() override { @@ -68,6 +242,7 @@ class npc_pet_mage_mirror_image : public CreatureScript me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE); } + Init(); } }; |