From 61f59acf8127536d02fde307baa45830769c2d13 Mon Sep 17 00:00:00 2001 From: Unholychick Date: Tue, 10 Jun 2014 17:24:54 +0200 Subject: Scripts/Ulduar: Implement Mimiron TODO: Make ACU hover properly (not fly, but hover). Fix laser barrage visual not always being infront of VX-001. Problem is caused by bad orientation update on spellcast. --- .../Northrend/Ulduar/Ulduar/boss_mimiron.cpp | 2937 +++++++++++++++++++- .../Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 79 +- .../scripts/Northrend/Ulduar/Ulduar/ulduar.h | 34 + 3 files changed, 3003 insertions(+), 47 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index f284aacf996..a3c3077fd71 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -15,10 +15,16 @@ * with this program. If not, see . */ +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellScript.h" +#include "SpellAuraEffects.h" #include "ulduar.h" +#include "Vehicle.h" enum Yells { @@ -39,78 +45,2927 @@ enum Yells SAY_BERSERK = 14 }; +enum ComputerYells +{ + SAY_SELF_DESTRUCT_INITIATED = 0, + SAY_SELF_DESTRUCT_TERMINATED = 1, + SAY_SELF_DESTRUCT_10 = 2, + SAY_SELF_DESTRUCT_9 = 3, + SAY_SELF_DESTRUCT_8 = 4, + SAY_SELF_DESTRUCT_7 = 5, + SAY_SELF_DESTRUCT_6 = 6, + SAY_SELF_DESTRUCT_5 = 7, + SAY_SELF_DESTRUCT_4 = 8, + SAY_SELF_DESTRUCT_3 = 9, + SAY_SELF_DESTRUCT_2 = 10, + SAY_SELF_DESTRUCT_1 = 11, + SAY_SELF_DESTRUCT_FINALIZED = 12 +}; + enum Spells { + // Mimiron + SPELL_WELD = 63339, // Idle aura. + SPELL_SEAT_1 = 52391, // Cast on all vehicles, Cycled on MKII + SPELL_SEAT_2 = 63313, // Cast on MKII and VX-001, Cycled on MKII + SPELL_SEAT_3 = 63314, // Cast on MKII, Cycled on MKII + SPELL_SEAT_5 = 63316, // Cast on MKII and VX-001, Cycled on MKII + SPELL_SEAT_6 = 63344, // Cast on MKII + SPELL_SEAT_7 = 63345, // Cast on MKII SPELL_JETPACK = 63341, - SPELL_EMERGENCY_MODE = 64582, - SPELL_SELF_REPAIR = 64383, - SPELL_MAGNETIC_CORE = 64444, + SPELL_DESPAWN_ASSAULT_BOTS = 64463, // only despawns assault bots... no equivalent spell for the other adds... + SPELL_TELEPORT_VISUAL = 41232, + SPELL_SLEEP_VISUAL_1 = 64393, + SPELL_SLEEP_VISUAL_2 = 64394, + // Leviathan MK II SPELL_FLAME_SUPPRESSANT_MK = 64570, SPELL_NAPALM_SHELL = 63666, - SPELL_PLASMA_BLAST = 62977, - SPELL_PROXIMITY_MINES = 63027, + SPELL_FORCE_CAST_NAPALM_SHELL = 64539, + SPELL_PLASMA_BLAST = 62997, + SPELL_SCRIPT_EFFECT_PLASMA_BLAST = 64542, SPELL_SHOCK_BLAST = 63631, - // VX 001 + SPELL_SHOCK_BLAST_AURA = 63632, // Deprecated? It is never cast. + + // VX-001 SPELL_FLAME_SUPPRESSANT_VX = 65192, - SPELL_FROSTBOMB = 64623, - SPELL_HAND_PULSE = 64348, SPELL_SPINNING_UP = 63414, - SPELL_RAPID_BURST = 63387, - SPELL_P3WX2_LASER_BARRAGE = 63293, - SPELL_ROCKET_STRIKE = 63041, - SPELL_HEAT_WAVE = 63677, + SPELL_HEAT_WAVE_AURA = 63679, + SPELL_HAND_PULSE_LEFT = 64348, + SPELL_HAND_PULSE_RIGHT = 64352, + SPELL_MOUNT_MKII = 64387, + SPELL_TORSO_DISABLED = 64120, + // Aerial Command Unit - SPELL_PLASMA_BALL = 63689, - // Additonal spells - SPELL_MAGNETIC_FIELD = 64668, - SPELL_DEAFENING_SIREN = 64616, + SPELL_PLASMA_BALL_P1 = 63689, + SPELL_PLASMA_BALL_P2 = 65647, + SPELL_MOUNT_VX_001 = 64388, + + // Proximity Mines + SPELL_PROXIMITY_MINES = 63027, // Cast by Leviathan MK II + SPELL_PROXIMITY_MINE_EXPLOSION = 66351, + SPELL_PROXIMITY_MINE_TRIGGER = 65346, + SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER = 65345, + SPELL_PERIODIC_PROXIMITY_AURA = 65345, + SPELL_SUMMON_PROXIMITY_MINE = 65347, + + // Rapid Burst + SPELL_RAPID_BURST_LEFT = 63387, + SPELL_RAPID_BURST_RIGHT = 64019, + SPELL_RAPID_BURST = 63382, // Cast by VX-001 + SPELL_RAPID_BURST_TARGET_ME = 64841, // Cast by Burst Target + SPELL_SUMMON_BURST_TARGET = 64840, // Cast by VX-001 + + // Rocket Strike + SPELL_SUMMON_ROCKET_STRIKE = 63036, + SPELL_SCRIPT_EFFECT_ROCKET_STRIKE = 63681, // Cast by Rocket (Mimiron Visual) + SPELL_ROCKET_STRIKE = 64064, // Added in creature_template_addon + SPELL_ROCKET_STRIKE_LEFT = 64402, // Cast by VX-001 + SPELL_ROCKET_STRIKE_BOTH = 65034, // Cast by VX-001 + + // Flames + SPELL_FLAMES_PERIODIC_TRIGGER = 64561, // Added in creature_template_addon + SPELL_SUMMON_FLAMES_SPREAD_TRIGGER = 64562, + SPELL_SUMMON_FLAMES_INITIAL = 64563, + SPELL_SUMMON_FLAMES_SPREAD = 64564, + SPELL_FLAMES = 64566, + SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL = 64567, + + // Frost Bomb + SPELL_SCRIPT_EFFECT_FROST_BOMB = 64623, // Cast by VX-001 + SPELL_FROST_BOMB_LINKED = 64624, // Added in creature_template_addon + SPELL_FROST_BOMB_DUMMY = 64625, + SPELL_SUMMON_FROST_BOMB = 64627, // Cast by VX-001 + SPELL_FROST_BOMB_EXPLOSION = 64626, + SPELL_CLEAR_FIRES = 65354, + + // Bots + SPELL_SUMMON_FIRE_BOT = 64622, + SPELL_SUMMON_FIRE_BOT_DUMMY = 64621, + SPELL_SUMMON_FIRE_BOT_TRIGGER = 64620, // Cast by Areal Command Unit + SPELL_DEAFENING_SIREN = 64616, // Added in creature_template_addon + SPELL_FIRE_SEARCH_AURA = 64617, // Added in creature_template_addon + SPELL_FIRE_SEARCH = 64618, SPELL_WATER_SPRAY = 64619, - SPELL_FROST_BOMB_HARD_MODE = 64627, - SPELL_EXPLOSION = 66351, - SPELL_DISARM = 1842, - SPELL_RIDE_VEHICLE = 46598, - SPELL_TRIGGER_MISSILE = 65347, + + SPELL_SUMMON_JUNK_BOT = 63819, + SPELL_SUMMON_JUNK_BOT_TRIGGER = 63820, // Cast by Areal Command Unit + SPELL_SUMMON_JUNK_BOT_DUMMY = 64398, + + SPELL_SUMMON_ASSAULT_BOT_TRIGGER = 64425, // Cast by Areal Command Unit + SPELL_SUMMON_ASSAULT_BOT_DUMMY = 64426, + SPELL_SUMMON_ASSAULT_BOT = 64427, + SPELL_MAGNETIC_FIELD = 64668, + + SPELL_SUMMON_BOMB_BOT = 63811, // Cast by Areal Command Unit + SPELL_BOMB_BOT_AURA = 63767, // Added in creature_template_addon + + // Miscellaneous + SPELL_SELF_DESTRUCTION_AURA = 64610, + SPELL_SELF_DESTRUCTION_VISUAL = 64613, + SPELL_NOT_SO_FRIENDLY_FIRE = 65040, + SPELL_ELEVATOR_KNOCKBACK = 65096, // Cast by worldtrigger. + SPELL_VEHICLE_DAMAGED = 63415, + SPELL_EMERGENCY_MODE = 64582, // mkii, vx001, aerial, assault, junk + SPELL_EMERGENCY_MODE_TURRET = 65101, // Cast by Leviathan MK II, only hits Leviathan MK II turret + SPELL_SELF_REPAIR = 64383, + SPELL_MAGNETIC_CORE = 64436, + SPELL_MAGNETIC_CORE_VISUAL = 64438, + SPELL_HALF_HEAL = 64188, + SPELL_CLEAR_ALL_DEBUFFS = 34098, // TODO: make use of this spell... + SPELL_FREEZE_ANIM_STUN = 63354, // used to prevent mkii from doing stuff?.. + SPELL_FREEZE_ANIM = 16245 // Idle aura. Freezes animation. +}; + +enum Data +{ + DATA_SETUP_MINE, + DATA_SETUP_BOMB, + DATA_SETUP_ROCKET, + DATA_NOT_SO_FRIENDLY_FIRE, + DATA_FIREFIGHTER, + DATA_WATERSPRAY, + DATA_MOVE_NEW +}; + +enum Events +{ + EVENT_NONE, + + // Leviathan MK II + EVENT_PROXIMITY_MINE, + EVENT_NAPALM_SHELL, + EVENT_PLASMA_BLAST, + EVENT_SHOCK_BLAST, + EVENT_FLAME_SUPPRESSANT_MK, + + // VX-001 + EVENT_RAPID_BURST, + EVENT_SPINNING_UP, + EVENT_ROCKET_STRIKE, + EVENT_HAND_PULSE, + EVENT_FROST_BOMB, + EVENT_FLAME_SUPPRESSANT_VX, + EVENT_RELOAD, + + // Aerial Command Unit + EVENT_SUMMON_FIRE_BOTS, + EVENT_SUMMON_JUNK_BOT, + EVENT_SUMMON_ASSAULT_BOT, + EVENT_SUMMON_BOMB_BOT, + + // Mimiron + EVENT_SUMMON_FLAMES, + EVENT_INTRO_1, + EVENT_INTRO_2, + EVENT_INTRO_3, + + EVENT_VX001_ACTIVATION_1, + EVENT_VX001_ACTIVATION_2, + EVENT_VX001_ACTIVATION_3, + EVENT_VX001_ACTIVATION_4, + EVENT_VX001_ACTIVATION_5, + EVENT_VX001_ACTIVATION_6, + EVENT_VX001_ACTIVATION_7, + EVENT_VX001_ACTIVATION_8, + EVENT_VX001_ACTIVATION_9, + + EVENT_AERIAL_ACTIVATION_1, + EVENT_AERIAL_ACTIVATION_2, + EVENT_AERIAL_ACTIVATION_3, + EVENT_AERIAL_ACTIVATION_4, + EVENT_AERIAL_ACTIVATION_5, + EVENT_AERIAL_ACTIVATION_6, + + EVENT_VOL7RON_ACTIVATION_1, + EVENT_VOL7RON_ACTIVATION_2, + EVENT_VOL7RON_ACTIVATION_3, + EVENT_VOL7RON_ACTIVATION_4, + EVENT_VOL7RON_ACTIVATION_5, + EVENT_VOL7RON_ACTIVATION_6, + EVENT_VOL7RON_ACTIVATION_7, + + EVENT_OUTTRO_1, + EVENT_OUTTRO_2, + EVENT_OUTTRO_3, + + // Computer + EVENT_SELF_DESTRUCT_10, + EVENT_SELF_DESTRUCT_9, + EVENT_SELF_DESTRUCT_8, + EVENT_SELF_DESTRUCT_7, + EVENT_SELF_DESTRUCT_6, + EVENT_SELF_DESTRUCT_5, + EVENT_SELF_DESTRUCT_4, + EVENT_SELF_DESTRUCT_3, + EVENT_SELF_DESTRUCT_2, + EVENT_SELF_DESTRUCT_1, + EVENT_SELF_DESTRUCT_FINALIZED +}; + +enum Actions +{ + DO_START_MKII, + DO_HARDMODE_MKII, + + DO_ACTIVATE_VX001, + DO_START_VX001, + DO_HARDMODE_VX001, + + DO_ACTIVATE_AERIAL, + DO_START_AERIAL, + DO_HARDMODE_AERIAL, + DO_DISABLE_AERIAL, + DO_ENABLE_AERIAL, + + DO_ACTIVATE_V0L7R0N_1, + DO_ACTIVATE_V0L7R0N_2, + DO_ASSEMBLED_COMBAT, // All 3 parts use this action, its done on purpose. + + DO_ACTIVATE_HARD_MODE, + DO_ACTIVATE_COMPUTER, + DO_DEACTIVATE_COMPUTER, + DO_ACTIVATE_SELF_DESTRUCT, + + DO_ENCOUNTER_DONE +}; + +enum Waypoints +{ + WP_NONE, + WP_MKII_P1_IDLE, + WP_MKII_P4_POS_1, + WP_MKII_P4_POS_2, + WP_MKII_P4_POS_3, + WP_MKII_P4_POS_4, + WP_MKII_P4_POS_5, + WP_AERIAL_P4_POS +}; + +enum Phases +{ + PHASE_NULL, + + // Leviathan MK II + PHASE_LEVIATHAN_SOLO, + PHASE_LEVIATHAN_ASSEMBLED, + + // VX-001 + PHASE_VX001_SOLO, + PHASE_VX001_ASSEMBLED, + + // Aerial Command Unit + PHASE_AERIAL_SOLO, + PHASE_AERIAL_ASSEMBLED +}; + +uint32 const repairSpells[4] = +{ + SPELL_SEAT_1, + SPELL_SEAT_2, + SPELL_SEAT_3, + SPELL_SEAT_5 +}; + +Position const pos[] = +{ + {}, + { 2792.070f, 2596.320f, 364.3136f }, // WP_MKII_P1_IDLE + { 2765.945f, 2571.095f, 364.0636f }, // WP_MKII_P4_POS_1 + { 2768.195f, 2573.095f, 364.0636f }, // WP_MKII_P4_POS_2 + { 2763.820f, 2568.870f, 364.3136f }, // WP_MKII_P4_POS_3 + { 2761.215f, 2568.875f, 364.0636f }, // WP_MKII_P4_POS_4 + { 2744.610f, 2569.380f, 364.3136f }, // WP_MKII_P4_POS_5 + { 2748.513f, 2569.051f, 364.3136f } // WP_AERIAL_P4_POS +}; + +class AerialTargetSelector +{ + public: + AerialTargetSelector() {} + + bool operator() (WorldObject* target) const + { + if (Unit* unit = target->ToUnit()) + { + if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return true; + + if (unit->GetVehicleBase()) + return true; + } + return false; + } }; -enum Npc +class EncounterDone { - NPC_ASSAULT_BOT = 34057, - NPC_BOMB_BOT = 33836, - NPC_JUNK_BOT = 33855, - NPC_EMERGENCE_FIRE_BOT = 34147, - NPC_FROST_BOMB = 34149, + Unit* _who; + Creature* _vehiclePart; + public: + EncounterDone(Unit* who, Creature* vehiclePart) : _who(who), _vehiclePart(vehiclePart) {} + + bool IsEncounterFinished() + { + if (InstanceScript* instance = _vehiclePart->GetInstanceScript()) + if (Creature* mkii = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(DATA_LEVIATHAN_MK_II))) + if (Creature* vx001 = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(DATA_VX_001))) + if (Creature* aerial = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(DATA_AERIAL_COMMAND_UNIT))) + if (mkii->getStandState() == UNIT_STAND_STATE_DEAD && vx001->getStandState() == UNIT_STAND_STATE_DEAD && aerial->getStandState() == UNIT_STAND_STATE_DEAD) + { + _who->Kill(mkii); + _who->Kill(vx001); + _who->Kill(aerial); + mkii->DespawnOrUnsummon(120000); + vx001->DespawnOrUnsummon(120000); + aerial->DespawnOrUnsummon(120000); + if (Creature* mimiron = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->JustDied(_who); + return true; + } + return false; + } }; -class spell_ulduar_proximity_mines : public SpellScriptLoader +class boss_mimiron : public CreatureScript { public: - spell_ulduar_proximity_mines() : SpellScriptLoader("spell_ulduar_proximity_mines") { } + boss_mimiron() : CreatureScript("boss_mimiron") { } - class spell_ulduar_proximity_minesSpellScript : public SpellScript + struct boss_mimironAI : public BossAI { - PrepareSpellScript(spell_ulduar_proximity_minesSpellScript); + boss_mimironAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) + { + me->SetReactState(REACT_PASSIVE); + me->SetDisableGravity(true); + } - void HandleScript(SpellEffIndex effIndex) + void DoAction(int32 action) override { - PreventHitDefaultEffect(effIndex); - for (uint8 i = 0; i < 10; ++i) - GetCaster()->CastSpell(GetCaster(), SPELL_TRIGGER_MISSILE, true); + switch (action) + { + case DO_ACTIVATE_VX001: + events.ScheduleEvent(EVENT_VX001_ACTIVATION_1, 1000); + break; + case DO_ACTIVATE_AERIAL: + events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_1, 5000); + break; + case DO_ACTIVATE_V0L7R0N_1: + Talk(SAY_AERIAL_DEATH); + if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) + mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_3, pos[WP_MKII_P4_POS_3]); // MovePoint(WP_MKII_P4_POS_1, pos[WP_MKII_P4_POS_1]); + break; + case DO_ACTIVATE_V0L7R0N_2: + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_1, 1000); + break; + case DO_ACTIVATE_HARD_MODE: + _fireFighter = true; + DoZoneInCombat(me); + break; + default: + break; + } } - void Register() override + void EnterCombat(Unit* /*who*/) override + { + if (!me->GetVehicleBase()) + return; + + _EnterCombat(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_WELD); + DoCast(me->GetVehicleBase(), SPELL_SEAT_6); + + if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON))) + button->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + if (_fireFighter) + events.ScheduleEvent(EVENT_SUMMON_FLAMES, 3000); + events.ScheduleEvent(EVENT_INTRO_1, 1500); + } + + void JustDied(Unit* /*who*/) override + { + instance->SetBossState(BOSS_MIMIRON, DONE); + events.Reset(); + me->CombatStop(true); + me->SetDisableGravity(false); + DoCast(me, SPELL_SLEEP_VISUAL_1); + DoCastAOE(SPELL_DESPAWN_ASSAULT_BOTS); + me->ExitVehicle(); + // ExitVehicle() offset position is not implemented, so we make up for that with MoveJump()... + me->GetMotionMaster()->MoveJump(me->GetPositionX() + (float)(10 * cos(me->GetOrientation())), me->GetPositionY() + (float)(10 * sin(me->GetOrientation())), me->GetPositionZ(), 10.0f, 5.0f); + events.ScheduleEvent(EVENT_OUTTRO_1, 7000); + } + + void Reset() override + { + if (instance->GetBossState(BOSS_MIMIRON) == DONE) // Mimiron will attempt to reset because he is not dead and will be set to friendly before despawning. + return; + + _Reset(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_ACTIVE); + + if (_fireFighter) + if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER))) + computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); + + if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON))) + { + button->SetGoState(GO_STATE_READY); + button->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_NOT_SELECTABLE); + } + + _fireFighter = false; + DoCast(me, SPELL_WELD); + + if (Unit* mkii = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) + DoCast(mkii, SPELL_SEAT_3); + } + + void UpdateAI(uint32 diff) override { - OnEffectHitTarget += SpellEffectFn(spell_ulduar_proximity_minesSpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + if ((!UpdateVictim() || !CheckInRoom()) && instance->GetBossState(BOSS_MIMIRON) != DONE) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SUMMON_FLAMES: + if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER))) + worldtrigger->CastSpell((Unit*)NULL, SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL, true, NULL, NULL, me->GetGUID()); + events.RescheduleEvent(EVENT_SUMMON_FLAMES, 28000); + break; + case EVENT_INTRO_1: + Talk(_fireFighter ? SAY_HARDMODE_ON : SAY_MKII_ACTIVATE); + events.ScheduleEvent(EVENT_INTRO_2, 5000); + break; + case EVENT_INTRO_2: + if (Unit* mkii = me->GetVehicleBase()) + { + DoCast(mkii, SPELL_SEAT_7); + mkii->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + mkii->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + } + events.ScheduleEvent(EVENT_INTRO_3, 2000); + break; + case EVENT_INTRO_3: + me->GetVehicleBase()->GetAI()->DoAction(_fireFighter? DO_HARDMODE_MKII : DO_START_MKII); + break; + case EVENT_VX001_ACTIVATION_1: + me->GetVehicleBase()->SetFacingTo(3.686f); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_2, 1000); + break; + case EVENT_VX001_ACTIVATION_2: + DoCast(me->GetVehicleBase(), SPELL_SEAT_6); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_3, 1000); + break; + case EVENT_VX001_ACTIVATION_3: + Talk(SAY_MKII_DEATH); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_4, 5000); + break; + case EVENT_VX001_ACTIVATION_4: + instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_READY); + if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER))) + worldtrigger->CastSpell(worldtrigger, SPELL_ELEVATOR_KNOCKBACK); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_5, 6000); + break; + case EVENT_VX001_ACTIVATION_5: + me->SummonCreature(NPC_VX_001, 2744.431f, 2569.385f, 364.3968f, 3.141593f, TEMPSUMMON_MANUAL_DESPAWN); + instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_ACTIVE_ALTERNATIVE); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_6, 19000); + break; + case EVENT_VX001_ACTIVATION_6: + if (Unit* vx001 = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_VX_001))) + DoCast(vx001, SPELL_SEAT_1); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_7, 3500); + break; + case EVENT_VX001_ACTIVATION_7: + Talk(SAY_VX001_ACTIVATE); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_8, 4000); + break; + case EVENT_VX001_ACTIVATION_8: + DoCast(me->GetVehicleBase(), SPELL_SEAT_2); + events.ScheduleEvent(EVENT_VX001_ACTIVATION_9, 3000); + break; + case EVENT_VX001_ACTIVATION_9: + me->GetVehicleBase()->GetAI()->DoAction(_fireFighter ? DO_HARDMODE_VX001 : DO_START_VX001); + break; + case EVENT_AERIAL_ACTIVATION_1: + DoCast(me->GetVehicleBase(), SPELL_SEAT_5); + events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_2, 2500); + break; + case EVENT_AERIAL_ACTIVATION_2: + Talk(SAY_VX001_DEATH); + events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_3, 5000); + break; + case EVENT_AERIAL_ACTIVATION_3: + me->SummonCreature(NPC_AERIAL_COMMAND_UNIT, 2744.65f, 2569.46f, 380, 0, TEMPSUMMON_MANUAL_DESPAWN); + events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_4, 5000); + break; + case EVENT_AERIAL_ACTIVATION_4: + if (Unit* aerial = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT))) + me->CastSpell(aerial, SPELL_SEAT_1); + events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_5, 2000); + break; + case EVENT_AERIAL_ACTIVATION_5: + Talk(SAY_AERIAL_ACTIVATE); + events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_6, 8000); + break; + case EVENT_AERIAL_ACTIVATION_6: + me->GetVehicleBase()->GetAI()->DoAction(_fireFighter? DO_HARDMODE_AERIAL : DO_START_AERIAL); + break; + case EVENT_VOL7RON_ACTIVATION_1: + if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) + mkii->SetFacingTo(M_PI); + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_2, 1000); + break; + case EVENT_VOL7RON_ACTIVATION_2: + if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) + if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001))) + { + vx001->RemoveAurasDueToSpell(SPELL_TORSO_DISABLED); + vx001->CastSpell(mkii, SPELL_MOUNT_MKII); + } + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_3, 4500); + break; + case EVENT_VOL7RON_ACTIVATION_3: + if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) + mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_5, pos[WP_MKII_P4_POS_5]); // MovePoint(WP_MKII_P4_POS_4, pos[WP_MKII_P4_POS_4]); + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_4, 5000); + break; + case EVENT_VOL7RON_ACTIVATION_4: + if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001))) + if (Creature* aerial = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT))) + { + aerial->GetMotionMaster()->MoveLand(0, (aerial->GetPositionX(), aerial->GetPositionY(), aerial->GetPositionZMinusOffset())); + //aerial->SetDisableGravity(false); + //aerial->SetHover(false); + aerial->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + aerial->CastSpell(vx001, SPELL_MOUNT_VX_001); + aerial->CastSpell(aerial, SPELL_HALF_HEAL); + } + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_5, 4000); + break; + case EVENT_VOL7RON_ACTIVATION_5: + Talk(SAY_V07TRON_ACTIVATE); + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_6, 3000); + break; + case EVENT_VOL7RON_ACTIVATION_6: + if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001))) + DoCast(vx001, SPELL_SEAT_2); + events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_7, 5000); + break; + case EVENT_VOL7RON_ACTIVATION_7: + for (uint8 data = DATA_LEVIATHAN_MK_II; data <= DATA_AERIAL_COMMAND_UNIT; data++) + if (Creature* mimironVehicle = ObjectAccessor::GetCreature(*me, instance->GetData64(data))) + mimironVehicle->AI()->DoAction(DO_ASSEMBLED_COMBAT); + break; + case EVENT_OUTTRO_1: + me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1); + DoCast(me, SPELL_SLEEP_VISUAL_2); + me->setFaction(35); + events.ScheduleEvent(EVENT_OUTTRO_2, 3000); + break; + case EVENT_OUTTRO_2: + Talk(SAY_V07TRON_DEATH); + if (_fireFighter) + { + if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER))) + computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); + me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.65f, 2569.46f, 364.314f, 3.14159f, 0, 0, 0.7f, 0.7f, 604800); + } + else + me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION, GO_CACHE_OF_INNOVATION_HERO), 2744.65f, 2569.46f, 364.314f, 3.14159f, 0, 0, 0.7f, 0.7f, 604800); + events.ScheduleEvent(EVENT_OUTTRO_3, 11000); + break; + case EVENT_OUTTRO_3: + DoCast(me, SPELL_TELEPORT_VISUAL); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->DespawnOrUnsummon(1000); // sniffs say 6 sec after, but it doesnt matter. + break; + default: + break; + } + } } + + private: + bool _fireFighter; }; - SpellScript* GetSpellScript() const override + CreatureAI* GetAI(Creature* creature) const override { - return new spell_ulduar_proximity_minesSpellScript(); + return GetUlduarAI(creature); } }; -void AddSC_boss_mimiron() +class boss_leviathan_mk_ii : public CreatureScript +{ + public: + boss_leviathan_mk_ii() : CreatureScript("boss_leviathan_mk_ii") { } + + struct boss_leviathan_mk_iiAI : public BossAI + { + boss_leviathan_mk_iiAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) + { + } + + void DamageTaken(Unit* who, uint32 &damage) override + { + if (damage >= me->GetHealth()) + { + damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth(). + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(me, SPELL_VEHICLE_DAMAGED, true); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); + + if (events.IsInPhase(PHASE_LEVIATHAN_SOLO)) + { + me->CastStop(); + if (Unit* turret = me->GetVehicleKit()->GetPassenger(3)) + turret->Kill(turret); + + me->SetSpeed(MOVE_RUN, 1.5f, true); + me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, pos[WP_MKII_P1_IDLE]); + } + else if (events.IsInPhase(PHASE_LEVIATHAN_ASSEMBLED)) + { + me->SetStandState(UNIT_STAND_STATE_DEAD); + + if (EncounterDone(who, me).IsEncounterFinished()) + return; + + me->CastStop(); + DoCast(me, SPELL_SELF_REPAIR); + } + events.Reset(); + } + } + + void DoAction(int32 action) override + { + switch (action) + { + case DO_HARDMODE_MKII: + _fireFighter = true; + DoCast(me, SPELL_EMERGENCY_MODE); + DoCastAOE(SPELL_EMERGENCY_MODE_TURRET); + events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_SOLO); + // Missing break intended. + case DO_START_MKII: + _setupMine = true; + _setupBomb = true; + _setupRocket = true; + + me->SetReactState(REACT_AGGRESSIVE); + events.SetPhase(PHASE_LEVIATHAN_SOLO); + + events.ScheduleEvent(EVENT_NAPALM_SHELL, 3000, 0, PHASE_LEVIATHAN_SOLO); + events.ScheduleEvent(EVENT_PLASMA_BLAST, 15000, 0, PHASE_LEVIATHAN_SOLO); + events.ScheduleEvent(EVENT_PROXIMITY_MINE, 5000); + events.ScheduleEvent(EVENT_SHOCK_BLAST, 18000); + break; + case DO_ASSEMBLED_COMBAT: + me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + + events.SetPhase(PHASE_LEVIATHAN_ASSEMBLED); + events.ScheduleEvent(EVENT_PROXIMITY_MINE, 15000); + events.ScheduleEvent(EVENT_SHOCK_BLAST, 45000); + break; + default: + break; + } + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_SETUP_MINE: + return _setupMine; + case DATA_SETUP_BOMB: + return _setupBomb; + case DATA_SETUP_ROCKET: + return _setupRocket; + case DATA_FIREFIGHTER: + return _fireFighter; + default: + return 0; + } + } + + void JustDied(Unit* /*who*/) override + { + _JustDied(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + if (mimiron->AI()) + mimiron->AI()->Talk(events.IsInPhase(PHASE_LEVIATHAN_SOLO) ? SAY_MKII_SLAY : SAY_V07TRON_SLAY); + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE) + return; + + switch (point) + { + case WP_MKII_P1_IDLE: + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_HALF_HEAL); + + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->DoAction(DO_ACTIVATE_VX001); + break; + case WP_MKII_P4_POS_1: + me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_2, pos[WP_MKII_P4_POS_2]); + break; + case WP_MKII_P4_POS_2: + me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_3, pos[WP_MKII_P4_POS_3]); + break; + case WP_MKII_P4_POS_3: + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_2); + break; + case WP_MKII_P4_POS_4: + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_5, pos[WP_MKII_P4_POS_5]); + break; + default: + break; + } + } + + void Reset() override + { + _Reset(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + _fireFighter = false; + _setupMine = false; + _setupBomb = false; + _setupRocket = false; + DoCast(me, SPELL_FREEZE_ANIM); + } + + void SetData(uint32 id, uint32 data) override + { + switch (id) + { + case DATA_SETUP_MINE: + _setupMine = data; + break; + case DATA_SETUP_BOMB: + _setupBomb = data; + break; + case DATA_SETUP_ROCKET: + _setupRocket = data; + break; + case DATA_FIREFIGHTER: + _fireFighter = data; + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() || !CheckInRoom()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_PROXIMITY_MINE: + DoCastAOE(SPELL_PROXIMITY_MINES); + events.RescheduleEvent(EVENT_PROXIMITY_MINE, 35000); + break; + case EVENT_PLASMA_BLAST: + DoCastVictim(SPELL_SCRIPT_EFFECT_PLASMA_BLAST); + events.RescheduleEvent(EVENT_PLASMA_BLAST, urand(30000, 45000), 0, PHASE_LEVIATHAN_SOLO); + + if (events.GetTimeUntilEvent(EVENT_NAPALM_SHELL) < 9000) + events.RescheduleEvent(EVENT_NAPALM_SHELL, 9000, 0, PHASE_LEVIATHAN_SOLO); // The actual spell is cast by the turret, we should not let it interrupt itself. + break; + case EVENT_SHOCK_BLAST: + DoCastAOE(SPELL_SHOCK_BLAST); + events.RescheduleEvent(EVENT_SHOCK_BLAST, urand(34000, 36000)); + break; + case EVENT_FLAME_SUPPRESSANT_MK: + DoCastAOE(SPELL_FLAME_SUPPRESSANT_MK); + events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_SOLO); + break; + case EVENT_NAPALM_SHELL: + DoCastAOE(SPELL_FORCE_CAST_NAPALM_SHELL); + events.RescheduleEvent(EVENT_NAPALM_SHELL, urand(6000, 15000), 0, PHASE_LEVIATHAN_SOLO); + + if (events.GetTimeUntilEvent(EVENT_PLASMA_BLAST) < 2000) + events.RescheduleEvent(EVENT_PLASMA_BLAST, 2000, 0, PHASE_LEVIATHAN_SOLO); // The actual spell is cast by the turret, we should not let it interrupt itself. + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + bool _fireFighter; + bool _setupMine; + bool _setupBomb; + bool _setupRocket; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class boss_vx_001 : public CreatureScript +{ + public: + boss_vx_001() : CreatureScript("boss_vx_001") { } + + struct boss_vx_001AI : public BossAI + { + boss_vx_001AI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) + { + me->SetDisableGravity(true); // This is the unfold visual state of VX-001, it has to be set on create as it requires an objectupdate if set later. + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SPECIAL_UNARMED); // This is a hack to force the yet to be unfolded visual state. + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_FREEZE_ANIM); + _fireFighter = false; + } + + void DamageTaken(Unit* who, uint32 &damage) override + { + if (damage >= me->GetHealth()) + { + damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth(). + me->AttackStop(); + me->SetUInt64Value(UNIT_FIELD_TARGET, NULL); // This should be removed when channel track target implementation is properly functioning. + DoCast(me, SPELL_VEHICLE_DAMAGED, true); + me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); + + if (events.IsInPhase(PHASE_VX001_SOLO)) + { + me->CastStop(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_HALF_HEAL); + DoCast(me, SPELL_TORSO_DISABLED); + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->DoAction(DO_ACTIVATE_AERIAL); + } + else if (events.IsInPhase(PHASE_VX001_ASSEMBLED)) + { + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (EncounterDone(who, me).IsEncounterFinished()) + return; + + me->CastStop(); + DoCast(me, SPELL_SELF_REPAIR); + } + events.Reset(); + } + } + + void DoAction(int32 action) override + { + switch (action) + { + case DO_HARDMODE_VX001: + _fireFighter = true; + DoCast(me, SPELL_EMERGENCY_MODE); + events.ScheduleEvent(EVENT_FROST_BOMB, 1000); + events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, 6000); + // Missing break intended. + case DO_START_VX001: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); // Remove emotestate. + //me->SetUInt32Value(UNIT_FIELD_BYTES_1, 33554432); Blizzard handles hover animation like this it seems. + DoCast(me, SPELL_HEAT_WAVE_AURA); + + events.SetPhase(PHASE_VX001_SOLO); + events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000); + events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000)); + events.ScheduleEvent(EVENT_RAPID_BURST, 500, 0, PHASE_VX001_SOLO); + break; + case DO_ASSEMBLED_COMBAT: + me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + + events.SetPhase(PHASE_VX001_ASSEMBLED); + events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000); + events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000)); + events.ScheduleEvent(EVENT_HAND_PULSE, 500, 0, PHASE_VX001_ASSEMBLED); + if (_fireFighter) + events.ScheduleEvent(EVENT_FROST_BOMB, 1000); + break; + default: + break; + } + } + + void EnterEvadeMode() override + { + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + if (summon->GetEntry() == NPC_BURST_TARGET) + summon->CastSpell(me, SPELL_RAPID_BURST_TARGET_ME); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + if (mimiron->AI()) + mimiron->AI()->Talk(events.IsInPhase(PHASE_VX001_SOLO) ? SAY_VX001_SLAY : SAY_V07TRON_SLAY); + } + + void SpellHit(Unit* caster, SpellInfo const* /*spellProto*/) override + { + if (caster->GetEntry() == NPC_BURST_TARGET && !me->HasUnitState(UNIT_STATE_CASTING)) + DoCast(caster, SPELL_RAPID_BURST); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + // Handle rotation during SPELL_SPINNING_UP, SPELL_P3WX2_LASER_BARRAGE, SPELL_RAPID_BURST, and SPELL_HAND_PULSE_LEFT/RIGHT + if (me->HasUnitState(UNIT_STATE_CASTING)) + { + if (Creature* channelTarget = ObjectAccessor::GetCreature(*me, me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT))) + me->SetFacingToObject(channelTarget); + return; + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RAPID_BURST: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true)) + DoCast(target, SPELL_SUMMON_BURST_TARGET); + events.RescheduleEvent(EVENT_RAPID_BURST, 3000, 0, PHASE_VX001_SOLO); + break; + case EVENT_ROCKET_STRIKE: + DoCastAOE(events.IsInPhase(PHASE_VX001_SOLO) ? SPELL_ROCKET_STRIKE_LEFT : SPELL_ROCKET_STRIKE_BOTH); + events.ScheduleEvent(EVENT_RELOAD, 10000); + events.RescheduleEvent(EVENT_ROCKET_STRIKE, urand(20000, 25000)); + break; + case EVENT_RELOAD: + for (uint8 seat = 6; seat <= 7; seat++) + if (Unit* rocket = me->GetVehicleKit()->GetPassenger(seat)) + rocket->SetDisplayId(rocket->GetNativeDisplayId()); + break; + case EVENT_HAND_PULSE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true)) + DoCast(target, urand(0,1) == 0 ? SPELL_HAND_PULSE_LEFT : SPELL_HAND_PULSE_RIGHT); + events.RescheduleEvent(EVENT_HAND_PULSE, urand(1500, 3000), 0, PHASE_VX001_ASSEMBLED); + break; + case EVENT_FROST_BOMB: + DoCastAOE(SPELL_SCRIPT_EFFECT_FROST_BOMB); + events.RescheduleEvent(EVENT_FROST_BOMB, 45000); + break; + case EVENT_SPINNING_UP: + DoCastAOE(SPELL_SPINNING_UP); + events.DelayEvents(14000); + events.RescheduleEvent(EVENT_SPINNING_UP, urand(55000, 65000)); + break; + case EVENT_FLAME_SUPPRESSANT_VX: + DoCastAOE(SPELL_FLAME_SUPPRESSANT_VX); + events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, urand(10000, 12000), 0, PHASE_VX001_SOLO); + break; + default: + break; + } + } + } + + private: + bool _fireFighter; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class boss_aerial_command_unit : public CreatureScript +{ + public: + boss_aerial_command_unit() : CreatureScript("boss_aerial_command_unit") { } + + struct boss_aerial_command_unitAI : public BossAI + { + boss_aerial_command_unitAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) + { + //me->SetDisableGravity(true); + me->SetReactState(REACT_PASSIVE); + fireFigther = false; + } + + void DamageTaken(Unit* who, uint32 &damage) override + { + if (damage >= me->GetHealth()) + { + damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth(). + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_VEHICLE_DAMAGED, true); + me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); + + if (events.IsInPhase(PHASE_AERIAL_SOLO)) + { + me->GetMotionMaster()->Clear(true); + me->GetMotionMaster()->MovePoint(WP_AERIAL_P4_POS, pos[WP_AERIAL_P4_POS]); + } + else if (events.IsInPhase(PHASE_AERIAL_ASSEMBLED)) + { + me->SetStandState(UNIT_STAND_STATE_DEAD); + + if (EncounterDone(who, me).IsEncounterFinished()) + return; + + me->CastStop(); + DoCast(me, SPELL_SELF_REPAIR); + } + events.Reset(); + } + } + + void DoAction(int32 action) override + { + switch (action) + { + case DO_HARDMODE_AERIAL: + fireFigther = true; + DoCast(me, SPELL_EMERGENCY_MODE); + events.ScheduleEvent(EVENT_SUMMON_FIRE_BOTS, 1000, 0, PHASE_AERIAL_SOLO); + // Missing break intended. + case DO_START_AERIAL: + //me->SetDisableGravity(false); + //me->SetHover(true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + + events.SetPhase(PHASE_AERIAL_SOLO); + events.ScheduleEvent(EVENT_SUMMON_JUNK_BOT, 5000, 0, PHASE_AERIAL_SOLO); + events.ScheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 9000, 0, PHASE_AERIAL_SOLO); + events.ScheduleEvent(EVENT_SUMMON_BOMB_BOT, 9000, 0, PHASE_AERIAL_SOLO); + break; + case DO_DISABLE_AERIAL: + //me->SetHover(false); + me->CastStop(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveFall(); + events.DelayEvents(23000); + break; + case DO_ENABLE_AERIAL: + //me->SetHover(true); + me->SetReactState(REACT_AGGRESSIVE); + break; + case DO_ASSEMBLED_COMBAT: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->SetStandState(UNIT_STAND_STATE_STAND); + events.SetPhase(PHASE_AERIAL_ASSEMBLED); + break; + default: + break; + } + } + + void EnterEvadeMode() override + { + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) override + { + if (fireFigther && (summon->GetEntry() == NPC_ASSAULT_BOT || summon->GetEntry() == NPC_JUNK_BOT)) + summon->AddAura(SPELL_EMERGENCY_MODE, summon); + BossAI::JustSummoned(summon); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + if (mimiron->AI()) + mimiron->AI()->Talk(events.IsInPhase(PHASE_AERIAL_SOLO) ? SAY_AERIAL_SLAY : SAY_V07TRON_SLAY); + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type == POINT_MOTION_TYPE && point == WP_AERIAL_P4_POS) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_1); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SUMMON_FIRE_BOTS: + DoCastAOE(SPELL_SUMMON_FIRE_BOT_TRIGGER); + events.RescheduleEvent(EVENT_SUMMON_FIRE_BOTS, 45000, 0, PHASE_AERIAL_SOLO); + break; + case EVENT_SUMMON_JUNK_BOT: + DoCastAOE(SPELL_SUMMON_JUNK_BOT_TRIGGER); + events.RescheduleEvent(EVENT_SUMMON_JUNK_BOT, urand(11000, 12000), 0, PHASE_AERIAL_SOLO); + break; + case EVENT_SUMMON_ASSAULT_BOT: + DoCastAOE(SPELL_SUMMON_ASSAULT_BOT_TRIGGER); + events.RescheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 30000, 0, PHASE_AERIAL_SOLO); + break; + case EVENT_SUMMON_BOMB_BOT: + DoCast(me, SPELL_SUMMON_BOMB_BOT); + events.RescheduleEvent(EVENT_SUMMON_BOMB_BOT, urand(15000, 20000), 0, PHASE_AERIAL_SOLO); + break; + default: + break; + } + } + DoSpellAttackIfReady(events.IsInPhase(PHASE_AERIAL_SOLO) ? SPELL_PLASMA_BALL_P1 : SPELL_PLASMA_BALL_P2); + } + + private: + bool fireFigther; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_magnetic_core : public CreatureScript +{ + public: + npc_magnetic_core() : CreatureScript("npc_magnetic_core") { } + + struct npc_magnetic_coreAI : public ScriptedAI + { + npc_magnetic_coreAI(Creature* creature) : ScriptedAI(creature) + { + DoCast(me, SPELL_MAGNETIC_CORE); + me->DespawnOrUnsummon(25000); // Just incase handling in aurascript fails to despawn. + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_mimiron_assault_bot : public CreatureScript { - new spell_ulduar_proximity_mines(); + public: + npc_mimiron_assault_bot() : CreatureScript("npc_mimiron_assault_bot") { } + + struct npc_mimiron_assault_botAI : public ScriptedAI + { + npc_mimiron_assault_botAI(Creature* creature) : ScriptedAI(creature) + { + magneticTimer = 14000; + } + + uint32 magneticTimer; + + void UpdateAI(uint32 diff) override + { + if (me->HasUnitState(UNIT_STATE_ROOT)) + if (Unit* newTarget = SelectTarget(SELECT_TARGET_NEAREST, 0, 30.0f, true)) + { + me->DeleteThreatList(); + AttackStart(newTarget); + } + + if (magneticTimer <= diff) + { + DoCastVictim(SPELL_MAGNETIC_FIELD); + me->ClearUnitState(UNIT_STATE_CASTING); + magneticTimer = 30000; + } + else magneticTimer -= diff; + + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_mimiron_emergency_fire_bot : public CreatureScript +{ + public: + npc_mimiron_emergency_fire_bot() : CreatureScript("npc_mimiron_emergency_fire_bot") { } + + struct npc_mimiron_emergency_fire_botAI : public ScriptedAI + { + npc_mimiron_emergency_fire_botAI(Creature* creature) : ScriptedAI(creature) + { + me->SetReactState(REACT_PASSIVE); + watersprayTimer = 7000; + isWaterSprayReady = true; + moveNew = true; + } + + uint32 watersprayTimer; + bool isWaterSprayReady; + bool moveNew; + + uint32 GetData(uint32 id) const override + { + if (id == DATA_WATERSPRAY) + return isWaterSprayReady; + if (id == DATA_MOVE_NEW) + return moveNew; + return 0; + } + + void SetData(uint32 id, uint32 data) override + { + if (id == DATA_WATERSPRAY) + isWaterSprayReady = false; + else if (id == DATA_MOVE_NEW) + moveNew = data; + } + + void UpdateAI(uint32 diff) override + { + if (!isWaterSprayReady) + { + if (watersprayTimer <= diff) + { + isWaterSprayReady = true; + watersprayTimer = urand(7000, 9000); + } + else watersprayTimer -= diff; + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_mimiron_computer : public CreatureScript +{ + public: + npc_mimiron_computer() : CreatureScript("npc_mimiron_computer") { } + + struct npc_mimiron_computerAI : public ScriptedAI + { + npc_mimiron_computerAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + } + + InstanceScript* instance; + EventMap events; + + void DoAction(int32 action) override + { + switch (action) + { + case DO_ACTIVATE_COMPUTER: + Talk(SAY_SELF_DESTRUCT_INITIATED); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_10, 3000); + break; + case DO_DEACTIVATE_COMPUTER: + Talk(SAY_SELF_DESTRUCT_TERMINATED); + me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_AURA); + me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_VISUAL); + events.Reset(); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SELF_DESTRUCT_10: + Talk(SAY_SELF_DESTRUCT_10); + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->DoAction(DO_ACTIVATE_HARD_MODE); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_9, 60000); + break; + case EVENT_SELF_DESTRUCT_9: + Talk(SAY_SELF_DESTRUCT_9); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_8, 60000); + break; + case EVENT_SELF_DESTRUCT_8: + Talk(SAY_SELF_DESTRUCT_8); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_7, 60000); + break; + case EVENT_SELF_DESTRUCT_7: + Talk(SAY_SELF_DESTRUCT_7); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_6, 60000); + break; + case EVENT_SELF_DESTRUCT_6: + Talk(SAY_SELF_DESTRUCT_6); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_5, 60000); + break; + case EVENT_SELF_DESTRUCT_5: + Talk(SAY_SELF_DESTRUCT_5); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_4, 60000); + break; + case EVENT_SELF_DESTRUCT_4: + Talk(SAY_SELF_DESTRUCT_4); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_3, 60000); + break; + case EVENT_SELF_DESTRUCT_3: + Talk(SAY_SELF_DESTRUCT_3); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_2, 60000); + break; + case EVENT_SELF_DESTRUCT_2: + Talk(SAY_SELF_DESTRUCT_2); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_1, 60000); + break; + case EVENT_SELF_DESTRUCT_1: + Talk(SAY_SELF_DESTRUCT_1); + events.ScheduleEvent(EVENT_SELF_DESTRUCT_FINALIZED, 60000); + break; + case EVENT_SELF_DESTRUCT_FINALIZED: + Talk(SAY_SELF_DESTRUCT_FINALIZED); + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) + mimiron->AI()->DoAction(DO_ACTIVATE_SELF_DESTRUCT); + DoCast(me, SPELL_SELF_DESTRUCTION_AURA); + DoCast(me, SPELL_SELF_DESTRUCTION_VISUAL); + break; + default: + break; + } + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_mimiron_flames : public CreatureScript +{ + public: + npc_mimiron_flames() : CreatureScript("npc_mimiron_flames") { } + + struct npc_mimiron_flamesAI : public ScriptedAI + { + npc_mimiron_flamesAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + timer = 4000; + spawnedFlames = false; + } + + uint32 timer; + bool spawnedFlames; + InstanceScript* instance; + + void UpdateAI(uint32 diff) override + { + if (instance->GetBossState(BOSS_MIMIRON) != IN_PROGRESS) + me->DespawnOrUnsummon(); + if (!spawnedFlames) + { + if (timer <= diff) + { + DoCastAOE(SPELL_SUMMON_FLAMES_SPREAD_TRIGGER); + spawnedFlames = true; + } + else timer -= diff; + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_mimiron_frost_bomb : public CreatureScript +{ + public: + npc_mimiron_frost_bomb() : CreatureScript("npc_mimiron_frost_bomb") { } + + struct npc_mimiron_frost_bombAI : public ScriptedAI + { + npc_mimiron_frost_bombAI(Creature* creature) : ScriptedAI(creature) + { + timer = 10000; + exploded = false; + } + + uint32 timer; + bool exploded; + + void UpdateAI(uint32 diff) override + { + if (timer <= diff) + { + if (!exploded) + { + DoCastAOE(SPELL_FROST_BOMB_EXPLOSION); + timer = 3000; + exploded = true; + } + else + { + DoCastAOE(SPELL_CLEAR_FIRES); + me->DespawnOrUnsummon(3000); + timer = 10000; + } + } + else timer -= diff; + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_mimiron_proximity_mine : public CreatureScript +{ + public: + npc_mimiron_proximity_mine() : CreatureScript("npc_mimiron_proximity_mine") { } + + struct npc_mimiron_proximity_mineAI : public ScriptedAI + { + npc_mimiron_proximity_mineAI(Creature* creature) : ScriptedAI(creature) + { + explosionTimer = 35000; + boom = false; + armed = false; + } + + uint32 explosionTimer; + bool boom; + bool armed; + + void UpdateAI(uint32 diff) override + { + if (!boom) + { + if (explosionTimer <= 33500 && !armed) + { + DoCast(me, SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER); + armed = true; + } + if (explosionTimer <= diff) + { + if (me->HasAura(SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER)) + DoCastAOE(SPELL_PROXIMITY_MINE_EXPLOSION); + boom = true; + me->DespawnOrUnsummon(1000); + } + else explosionTimer -= diff; + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class go_mimiron_hardmode_button : public GameObjectScript +{ +public: + go_mimiron_hardmode_button() : GameObjectScript("go_mimiron_hardmode_button") { } + + bool OnGossipHello(Player* /*player*/, GameObject* go) + { + InstanceScript* instance = go->GetInstanceScript(); + + if (!instance) + return false; + + if (Creature* computer = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_COMPUTER))) + computer->AI()->DoAction(DO_ACTIVATE_COMPUTER); + go->SetGoState(GO_STATE_ACTIVE); + go->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_NOT_SELECTABLE); + return true; + } +}; + +// 63801 Bomb Bot +class spell_mimiron_bomb_bot : public SpellScriptLoader +{ + public: + spell_mimiron_bomb_bot() : SpellScriptLoader("spell_mimiron_bomb_bot") { } + + class spell_mimiron_bomb_bot_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_bomb_bot_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (GetHitPlayer()) + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* mkii = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_LEVIATHAN_MK_II))) + mkii->AI()->SetData(DATA_SETUP_BOMB, 0); + } + + void HandleDespawn(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()->IsSummon()) + { + GetHitUnit()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + GetHitUnit()->ToTempSummon()->DespawnOrUnsummon(1000); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_bomb_bot_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_bomb_bot_SpellScript::HandleDespawn, EFFECT_1, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_bomb_bot_SpellScript(); + } +}; + +// 65192 - Flame Suppressant, 65224 - Clear Fires, 65354 - Clear Fires, 64619 - Water Spray +class spell_mimiron_clear_fires : public SpellScriptLoader +{ + public: + spell_mimiron_clear_fires() : SpellScriptLoader("spell_mimiron_clear_fires") { } + + class spell_mimiron_clear_fires_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_clear_fires_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()->IsSummon()) + GetHitUnit()->ToTempSummon()->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_clear_fires_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_clear_fires_SpellScript(); + } +}; + +// 64463 - Despawn Assault Bots +class spell_mimiron_despawn_assault_bots : public SpellScriptLoader +{ + public: + spell_mimiron_despawn_assault_bots() : SpellScriptLoader("spell_mimiron_despawn_assault_bots") { } + + class spell_mimiron_despawn_assault_bots_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_despawn_assault_bots_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit()->IsSummon()) + GetHitUnit()->ToTempSummon()->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_despawn_assault_bots_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_despawn_assault_bots_SpellScript(); + } +}; + +// 64626 - Explosion +class spell_mimiron_frost_bomb_explosion : public SpellScriptLoader +{ + public: + spell_mimiron_frost_bomb_explosion() : SpellScriptLoader("spell_mimiron_frost_bomb_explosion") { } + + class spell_mimiron_frost_bomb_explosion_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_frost_bomb_explosion_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->RemoveAurasDueToSpell(SPELL_FLAMES_PERIODIC_TRIGGER); + } + + void HandleUnaura(SpellEffIndex /*effIndex*/) + { + GetCaster()->RemoveAurasDueToSpell(SPELL_FROST_BOMB_LINKED); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_mimiron_frost_bomb_explosion_SpellScript::HandleUnaura, EFFECT_2, SPELL_EFFECT_DUMMY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_frost_bomb_explosion_SpellScript::HandleDummy, EFFECT_2, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_frost_bomb_explosion_SpellScript(); + } +}; + +// 64618 - Fire Search +class spell_mimiron_fire_search : public SpellScriptLoader +{ + public: + spell_mimiron_fire_search() : SpellScriptLoader("spell_mimiron_fire_search") { } + + class spell_mimiron_fire_search_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_fire_search_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_WATER_SPRAY)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + { + GetCaster()->GetMotionMaster()->MoveRandom(15.0f); + return; + } + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.clear(); + targets.push_back(target); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + + if (caster->GetAI()) + { + if (caster->GetDistance2d(GetHitUnit()) <= 15.0f && caster->GetAI()->GetData(DATA_WATERSPRAY)) + { + caster->CastSpell(GetHitUnit(), SPELL_WATER_SPRAY, true); + caster->GetAI()->SetData(DATA_WATERSPRAY, 0); + caster->GetAI()->SetData(DATA_MOVE_NEW, 1); + } + else if (caster->GetAI()->GetData(DATA_MOVE_NEW)) + { + caster->GetMotionMaster()->MoveChase(GetHitUnit()); + caster->GetAI()->SetData(DATA_MOVE_NEW, 0); + } + } + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_fire_search_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_fire_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_fire_search_SpellScript(); + } +}; + +// 64570 - Flame Suppressant +class spell_mimiron_flame_suppressant : public SpellScriptLoader +{ + public: + spell_mimiron_flame_suppressant() : SpellScriptLoader("spell_mimiron_flame_suppressant") { } + + class spell_mimiron_flame_suppressant_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_flame_suppressant_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->RemoveAurasDueToSpell(SPELL_FLAMES_PERIODIC_TRIGGER); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_flame_suppressant_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_flame_suppressant_SpellScript(); + } +}; + +// 64436 - Magnetic Core +class spell_mimiron_magnetic_core : public SpellScriptLoader +{ + public: + spell_mimiron_magnetic_core() : SpellScriptLoader("spell_mimiron_magnetic_core") { } + + class spell_mimiron_magnetic_core_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_magnetic_core_SpellScript); + + void FilterTargets(std::list& targets) + { + targets.remove_if(AerialTargetSelector()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_magnetic_core_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_magnetic_core_SpellScript(); + } + + class spell_mimiron_magnetic_core_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_magnetic_core_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGNETIC_CORE_VISUAL)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + if (target->GetAI()) + target->GetAI()->DoAction(DO_DISABLE_AERIAL); + + target->CastSpell(target, SPELL_MAGNETIC_CORE_VISUAL, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + if (target->GetAI()) + target->GetAI()->DoAction(DO_ENABLE_AERIAL); + + target->RemoveAurasDueToSpell(SPELL_MAGNETIC_CORE_VISUAL); + } + + void OnRemoveSelf(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->ToCreature()) + GetTarget()->ToCreature()->DespawnOrUnsummon(); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_mimiron_magnetic_core_AuraScript::OnApply, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_mimiron_magnetic_core_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_mimiron_magnetic_core_AuraScript::OnRemoveSelf, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_magnetic_core_AuraScript(); + } +}; + +// 63667 - Napalm Shell +class spell_mimiron_napalm_shell : public SpellScriptLoader +{ + public: + spell_mimiron_napalm_shell() : SpellScriptLoader("spell_mimiron_napalm_shell") { } + + class spell_mimiron_napalm_shell_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_napalm_shell_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_NAPALM_SHELL)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.remove_if(Trinity::AllWorldObjectsInRange(GetCaster(), 15.0f)); + + if (!targets.empty()) + target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.clear(); + targets.push_back(target); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_NAPALM_SHELL); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_napalm_shell_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_napalm_shell_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_napalm_shell_SpellScript(); + } +}; + +// 63274 - P3Wx2 Laser Barrage -- This should be removed when channel track target implementation is properly functioning. +class spell_mimiron_p3wx2_laser_barrage : public SpellScriptLoader +{ + public: + spell_mimiron_p3wx2_laser_barrage() : SpellScriptLoader("spell_mimiron_p3wx2_laser_barrage") { } + + class spell_mimiron_p3wx2_laser_barrage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_p3wx2_laser_barrage_SpellScript); + + void OnHit(SpellEffIndex /*effIndex*/) + { + GetCaster()->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, GetHitUnit()->GetGUID()); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_p3wx2_laser_barrage_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_p3wx2_laser_barrage_SpellScript(); + } +}; + +// 64542 - Plasma Blast +class spell_mimiron_plasma_blast : public SpellScriptLoader +{ + public: + spell_mimiron_plasma_blast() : SpellScriptLoader("spell_mimiron_plasma_blast") { } + + class spell_mimiron_plasma_blast_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_plasma_blast_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PLASMA_BLAST)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetVehicleKit(); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()->GetVehicleKit()->GetPassenger(3)) + caster->CastSpell(GetHitUnit(), SPELL_PLASMA_BLAST); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_plasma_blast_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_plasma_blast_SpellScript(); + } +}; + +// 66351 - Explosion +class spell_mimiron_proximity_explosion : public SpellScriptLoader +{ + public: + spell_mimiron_proximity_explosion() : SpellScriptLoader("spell_mimiron_proximity_explosion") { } + + class spell_mimiron_proximity_explosion_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_proximity_explosion_SpellScript); + + void OnHit(SpellEffIndex /*effIndex*/) + { + if (GetHitPlayer()) + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* mkII = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_LEVIATHAN_MK_II))) + mkII->AI()->SetData(DATA_SETUP_MINE, 0); + } + + void HandleAura(SpellEffIndex /*effIndex*/) + { + GetCaster()->RemoveAurasDueToSpell(SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_proximity_explosion_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_proximity_explosion_SpellScript::HandleAura, EFFECT_1, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_proximity_explosion_SpellScript(); + } +}; + +// 63027 - Proximity Mines +class spell_mimiron_proximity_mines : public SpellScriptLoader +{ + public: + spell_mimiron_proximity_mines() : SpellScriptLoader("spell_mimiron_proximity_mines") { } + + class spell_mimiron_proximity_mines_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_proximity_mines_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_PROXIMITY_MINE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + for (uint8 i = 0; i < 10; ++i) + GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_PROXIMITY_MINE, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_proximity_mines_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_proximity_mines_SpellScript(); + } +}; + +// 65346 - Proximity Mine +class spell_mimiron_proximity_trigger : public SpellScriptLoader +{ + public: + spell_mimiron_proximity_trigger() : SpellScriptLoader("spell_mimiron_proximity_trigger") { } + + class spell_mimiron_proximity_trigger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_proximity_trigger_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PROXIMITY_MINE_EXPLOSION)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + targets.remove(GetExplTargetWorldObject()); + + if (targets.empty()) + FinishCast(SPELL_FAILED_NO_VALID_TARGETS); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell((Unit*)NULL, SPELL_PROXIMITY_MINE_EXPLOSION, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_proximity_trigger_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHit += SpellEffectFn(spell_mimiron_proximity_trigger_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_proximity_trigger_SpellScript(); + } +}; + +// 63382 - Rapid Burst +class spell_mimiron_rapid_burst : public SpellScriptLoader +{ + public: + spell_mimiron_rapid_burst() : SpellScriptLoader("spell_mimiron_rapid_burst") { } + + class spell_mimiron_rapid_burst_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_rapid_burst_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_RAPID_BURST_LEFT) || !sSpellMgr->GetSpellInfo(SPELL_RAPID_BURST_RIGHT)) + return false; + return true; + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->IsSummon()) + GetTarget()->ToTempSummon()->DespawnOrUnsummon(); + } + + void HandleDummyTick(AuraEffect const* aurEff) + { + if (GetCaster()) + GetCaster()->CastSpell(GetTarget(), aurEff->GetTickNumber() % 2 == 0 ? SPELL_RAPID_BURST_RIGHT : SPELL_RAPID_BURST_LEFT, true, NULL, aurEff); + } + + void Register() override + { + AfterEffectRemove += AuraEffectApplyFn(spell_mimiron_rapid_burst_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_rapid_burst_AuraScript::HandleDummyTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_rapid_burst_AuraScript(); + } +}; + +// 64402 - Rocket Strike, 65034 - Rocket Strike +class spell_mimiron_rocket_strike : public SpellScriptLoader +{ + public: + spell_mimiron_rocket_strike() : SpellScriptLoader("spell_mimiron_rocket_strike") { } + + class spell_mimiron_rocket_strike_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_rocket_strike_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SCRIPT_EFFECT_ROCKET_STRIKE)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + if (m_scriptSpellId == SPELL_ROCKET_STRIKE_LEFT && GetCaster()->IsVehicle()) + if (WorldObject* target = GetCaster()->GetVehicleKit()->GetPassenger(6)) + { + targets.clear(); + targets.push_back(target); + } + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell((Unit*)NULL, SPELL_SCRIPT_EFFECT_ROCKET_STRIKE, true, NULL, NULL, GetCaster()->GetGUID()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_rocket_strike_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_rocket_strike_SpellScript(); + } +}; + +// 63041 - Rocket Strike +class spell_mimiron_rocket_strike_damage : public SpellScriptLoader +{ + public: + spell_mimiron_rocket_strike_damage() : SpellScriptLoader("spell_mimiron_rocket_strike_damage") { } + + class spell_mimiron_rocket_strike_damage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_rocket_strike_damage_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_NOT_SO_FRIENDLY_FIRE)) + return false; + return true; + } + + void HandleDespawn(SpellEffIndex /*effIndex*/) + { + if (GetCaster()->IsSummon()) + GetCaster()->ToTempSummon()->DespawnOrUnsummon(1000); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (GetHitPlayer()) + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* mkii = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_LEVIATHAN_MK_II))) + mkii->AI()->SetData(DATA_SETUP_ROCKET, 0); + } + + void HandleFriendlyFire(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell((Unit*)NULL, SPELL_NOT_SO_FRIENDLY_FIRE, true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_mimiron_rocket_strike_damage_SpellScript::HandleDespawn, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_damage_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_damage_SpellScript::HandleFriendlyFire, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_rocket_strike_damage_SpellScript(); + } +}; + +// 63681 - Rocket Strike +class spell_mimiron_rocket_strike_target_select : public SpellScriptLoader +{ + public: + spell_mimiron_rocket_strike_target_select() : SpellScriptLoader("spell_mimiron_rocket_strike_target_select") { } + + class spell_mimiron_rocket_strike_target_select_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_rocket_strike_target_select_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ROCKET_STRIKE)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.remove_if(Trinity::AllWorldObjectsInRange(GetCaster(), 15.0f)); + + if (!targets.empty()) + target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.clear(); + targets.push_back(target); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + InstanceScript* instance = GetCaster()->GetInstanceScript(); + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ROCKET_STRIKE, true, NULL, NULL, instance ? instance->GetData64(DATA_VX_001) : GetCaster()->GetGUID()); + GetCaster()->SetDisplayId(11686); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_rocket_strike_target_select_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_target_select_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_rocket_strike_target_select_SpellScript(); + } +}; + +// 64383 - Self Repair +class spell_mimiron_self_repair : public SpellScriptLoader +{ + public: + spell_mimiron_self_repair() : SpellScriptLoader("spell_mimiron_self_repair") { } + + class spell_mimiron_self_repair_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_self_repair_SpellScript); + + void HandleScript() + { + if (GetCaster()->GetAI()) + GetCaster()->GetAI()->DoAction(DO_ASSEMBLED_COMBAT); + } + + void Register() override + { + AfterHit += SpellHitFn(spell_mimiron_self_repair_SpellScript::HandleScript); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_self_repair_SpellScript(); + } +}; + +// 63414 - Spinning Up -- This should be removed when channel track target implementation is properly functioning. +class spell_mimiron_spinning_up : public SpellScriptLoader +{ + public: + spell_mimiron_spinning_up() : SpellScriptLoader("spell_mimiron_spinning_up") { } + + class spell_mimiron_spinning_up_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_spinning_up_SpellScript); + + void OnHit(SpellEffIndex /*effIndex*/) + { + if (GetHitUnit() != GetCaster()) + GetCaster()->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, GetHitUnit()->GetGUID()); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_spinning_up_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_spinning_up_SpellScript(); + } +}; + +// 64426 - Summon Scrap Bot +class spell_mimiron_summon_assault_bot : public SpellScriptLoader +{ + public: + spell_mimiron_summon_assault_bot() : SpellScriptLoader("spell_mimiron_summon_assault_bot") { } + + class spell_mimiron_summon_assault_bot_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_summon_assault_bot_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ASSAULT_BOT)) + return false; + return true; + } + + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (InstanceScript* instance = caster->GetInstanceScript()) + if (instance->GetBossState(BOSS_MIMIRON) == IN_PROGRESS) + caster->CastSpell(caster, SPELL_SUMMON_ASSAULT_BOT, false, NULL, aurEff, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_mimiron_summon_assault_bot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_summon_assault_bot_AuraScript(); + } +}; + +// 64425 - Summon Scrap Bot Trigger +class spell_mimiron_summon_assault_bot_target : public SpellScriptLoader +{ + public: + spell_mimiron_summon_assault_bot_target() : SpellScriptLoader("spell_mimiron_summon_assault_bot_target") { } + + class spell_mimiron_summon_assault_bot_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_assault_bot_target_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ASSAULT_BOT_DUMMY)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.clear(); + targets.push_back(target); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_ASSAULT_BOT_DUMMY, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_assault_bot_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_assault_bot_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_assault_bot_target_SpellScript(); + } +}; + +// 64621 - Summon Fire Bot +class spell_mimiron_summon_fire_bot : public SpellScriptLoader +{ + public: + spell_mimiron_summon_fire_bot() : SpellScriptLoader("spell_mimiron_summon_fire_bot") { } + + class spell_mimiron_summon_fire_bot_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_summon_fire_bot_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FIRE_BOT)) + return false; + + return true; + } + + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (InstanceScript* instance = caster->GetInstanceScript()) + if (instance->GetBossState(BOSS_MIMIRON) == IN_PROGRESS) + caster->CastSpell(caster, SPELL_SUMMON_FIRE_BOT, false, NULL, aurEff, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_mimiron_summon_fire_bot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_summon_fire_bot_AuraScript(); + } +}; + +// 64620 - Summon Fire Bot Trigger +class spell_mimiron_summon_fire_bot_target : public SpellScriptLoader +{ + public: + spell_mimiron_summon_fire_bot_target() : SpellScriptLoader("spell_mimiron_summon_fire_bot_target") { } + + class spell_mimiron_summon_fire_bot_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_fire_bot_target_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FIRE_BOT_DUMMY)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + Trinity::Containers::RandomResizeList(targets, 3); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_FIRE_BOT_DUMMY, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_fire_bot_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_fire_bot_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_fire_bot_target_SpellScript(); + } +}; + +// 64567 - Summon Flames Initial +class spell_mimiron_summon_flames_initial : public SpellScriptLoader +{ + public: + spell_mimiron_summon_flames_initial() : SpellScriptLoader("spell_mimiron_summon_flames_initial") { } + + class spell_mimiron_summon_flames_initial_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_flames_initial_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FLAMES_INITIAL)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + Trinity::Containers::RandomResizeList(targets, 3); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_FLAMES_INITIAL, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_flames_initial_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_flames_initial_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_flames_initial_SpellScript(); + } +}; + +// 64562 - Summon Flames Spread Trigger +class spell_mimiron_summon_flames_spread : public SpellScriptLoader +{ + public: + spell_mimiron_summon_flames_spread() : SpellScriptLoader("spell_mimiron_summon_flames_spread") { } + + class spell_mimiron_summon_flames_spread_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_flames_spread_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + WorldObject* target = targets.front(); + + for (std::list::const_iterator iter = targets.begin(); iter != targets.end(); iter++) + if (GetCaster()->GetDistance2d(*iter) < GetCaster()->GetDistance2d(target)) + target = *iter; + + targets.clear(); + targets.push_back(target); + } + + void OnHit(SpellEffIndex /*effIndex*/) + { + GetCaster()->SetInFront(GetHitUnit()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_flames_spread_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_flames_spread_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_flames_spread_SpellScript(); + } + + class spell_mimiron_summon_flames_spread_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_summon_flames_spread_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FLAMES_SPREAD)) + return false; + return true; + } + + void HandleTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + if (caster->HasAura(SPELL_FLAMES_PERIODIC_TRIGGER)) + caster->CastSpell(GetTarget(), SPELL_SUMMON_FLAMES_SPREAD, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_summon_flames_spread_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_summon_flames_spread_AuraScript(); + } +}; + +// 64627 - Frost Bomb +class spell_mimiron_summon_frost_bomb : public SpellScriptLoader +{ + public: + spell_mimiron_summon_frost_bomb() : SpellScriptLoader("spell_mimiron_summon_frost_bomb") { } + + class spell_mimiron_summon_frost_bomb_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_frost_bomb_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->RemoveAurasDueToSpell(SPELL_FLAMES_PERIODIC_TRIGGER); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_frost_bomb_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_frost_bomb_SpellScript(); + } +}; + +// 64623 - Frost Bomb +class spell_mimiron_summon_frost_bomb_target : public SpellScriptLoader +{ + public: + spell_mimiron_summon_frost_bomb_target() : SpellScriptLoader("spell_mimiron_summon_frost_bomb_target") { } + + class spell_mimiron_summon_frost_bomb_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_frost_bomb_target_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FROST_BOMB)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + targets.remove_if(Trinity::AllWorldObjectsInRange(GetCaster(), 15.0f)); + + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.clear(); + targets.push_back(target); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_FROST_BOMB, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_frost_bomb_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_frost_bomb_target_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_frost_bomb_target_SpellScript(); + } +}; + +// 64398 - Summon Scrap Bot +class spell_mimiron_summon_junk_bot : public SpellScriptLoader +{ + public: + spell_mimiron_summon_junk_bot() : SpellScriptLoader("spell_mimiron_summon_junk_bot") { } + + class spell_mimiron_summon_junk_bot_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_summon_junk_bot_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_JUNK_BOT)) + return false; + return true; + } + + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (InstanceScript* instance = caster->GetInstanceScript()) + if (instance->GetBossState(BOSS_MIMIRON) == IN_PROGRESS) + caster->CastSpell(caster, SPELL_SUMMON_JUNK_BOT, false, NULL, aurEff, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_mimiron_summon_junk_bot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_summon_junk_bot_AuraScript(); + } +}; + +// 63820 - Summon Scrap Bot Trigger +class spell_mimiron_summon_junk_bot_target : public SpellScriptLoader +{ + public: + spell_mimiron_summon_junk_bot_target() : SpellScriptLoader("spell_mimiron_summon_junk_bot_target") { } + + class spell_mimiron_summon_junk_bot_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mimiron_summon_junk_bot_target_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_JUNK_BOT_DUMMY)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + + targets.clear(); + targets.push_back(target); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_JUNK_BOT_DUMMY, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_junk_bot_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_junk_bot_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_mimiron_summon_junk_bot_target_SpellScript(); + } +}; + +// 63339 - Weld +class spell_mimiron_weld : public SpellScriptLoader +{ + public: + spell_mimiron_weld() : SpellScriptLoader("spell_mimiron_weld") { } + + class spell_mimiron_weld_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mimiron_weld_AuraScript); + + void HandleTick(AuraEffect const* aurEff) + { + Unit* caster = GetTarget(); + if (Unit* vehicle = caster->GetVehicleBase()) + { + if (aurEff->GetTickNumber() % 5 == 0) + caster->CastSpell(vehicle, repairSpells[urand(0, 3)]); + caster->SetFacingToObject(vehicle); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_weld_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mimiron_weld_AuraScript(); + } +}; + +class achievement_setup_boom : public AchievementCriteriaScript +{ + public: + achievement_setup_boom() : AchievementCriteriaScript("achievement_setup_boom") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_SETUP_BOMB); + } +}; + +class achievement_setup_mine : public AchievementCriteriaScript +{ + public: + achievement_setup_mine() : AchievementCriteriaScript("achievement_setup_mine") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_SETUP_MINE); + } +}; + +class achievement_setup_rocket : public AchievementCriteriaScript +{ + public: + achievement_setup_rocket() : AchievementCriteriaScript("achievement_setup_rocket") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_SETUP_ROCKET); + } +}; + +class achievement_firefighter : public AchievementCriteriaScript +{ + public: + achievement_firefighter() : AchievementCriteriaScript("achievement_firefighter") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + return target && target->GetAI()->GetData(DATA_FIREFIGHTER); + } +}; + +void AddSC_boss_mimiron() +{ + new boss_aerial_command_unit(); + new boss_leviathan_mk_ii(); + new boss_mimiron(); + new boss_vx_001(); + + new npc_magnetic_core(); + new npc_mimiron_assault_bot(); + new npc_mimiron_emergency_fire_bot(); + new npc_mimiron_computer(); + new npc_mimiron_flames(); + new npc_mimiron_frost_bomb(); + new npc_mimiron_proximity_mine(); + + new go_mimiron_hardmode_button(); + + new spell_mimiron_bomb_bot(); + new spell_mimiron_clear_fires(); + new spell_mimiron_despawn_assault_bots(); + new spell_mimiron_fire_search(); + new spell_mimiron_flame_suppressant(); + new spell_mimiron_frost_bomb_explosion(); + new spell_mimiron_magnetic_core(); + new spell_mimiron_napalm_shell(); + new spell_mimiron_p3wx2_laser_barrage(); + new spell_mimiron_plasma_blast(); + new spell_mimiron_proximity_explosion(); + new spell_mimiron_proximity_mines(); + new spell_mimiron_proximity_trigger(); + new spell_mimiron_rapid_burst(); + new spell_mimiron_rocket_strike(); + new spell_mimiron_rocket_strike_damage(); + new spell_mimiron_rocket_strike_target_select(); + new spell_mimiron_self_repair(); + new spell_mimiron_spinning_up(); + new spell_mimiron_summon_assault_bot(); + new spell_mimiron_summon_assault_bot_target(); + new spell_mimiron_summon_fire_bot(); + new spell_mimiron_summon_fire_bot_target(); + new spell_mimiron_summon_flames_initial(); + new spell_mimiron_summon_flames_spread(); + new spell_mimiron_summon_frost_bomb(); + new spell_mimiron_summon_frost_bomb_target(); + new spell_mimiron_summon_junk_bot(); + new spell_mimiron_summon_junk_bot_target(); + new spell_mimiron_weld(); + + new achievement_setup_boom(); + new achievement_setup_mine(); + new achievement_setup_rocket(); + new achievement_firefighter(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index d728bc2a898..4dfa38abae5 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -31,6 +31,9 @@ static DoorData const doorData[] = { GO_HODIR_ENTRANCE, BOSS_HODIR, DOOR_TYPE_ROOM, BOUNDARY_E }, { GO_HODIR_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, { GO_HODIR_ICE_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_W }, + { GO_MIMIRON_DOOR_1, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_W }, + { GO_MIMIRON_DOOR_2, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_E }, + { GO_MIMIRON_DOOR_3, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_S }, { GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE, BOUNDARY_E }, { GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S }, { GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, @@ -69,11 +72,14 @@ class instance_ulduar : public InstanceMapScript uint64 AssemblyGUIDs[3]; uint64 KologarnGUID; uint64 AuriayaGUID; - uint64 MimironGUID; uint64 HodirGUID; uint64 ThorimGUID; uint64 FreyaGUID; uint64 ElderGUIDs[3]; + uint64 MimironGUID; + uint64 MimironVehicleGUIDs[3]; + uint64 MimironComputerGUID; + uint64 MimironWorldTriggerGUID; uint64 VezaxGUID; uint64 YoggSaronGUID; uint64 VoiceOfYoggSaronGUID; @@ -91,6 +97,9 @@ class instance_ulduar : public InstanceMapScript uint64 ThorimChestGUID; uint64 HodirRareCacheGUID; uint64 HodirChestGUID; + uint64 MimironTramGUID; + uint64 MimironElevatorGUID; + uint64 MimironButtonGUID; uint64 BrainRoomDoorGUIDs[3]; uint64 AlgalonSigilDoorGUID[3]; uint64 AlgalonFloorGUID[2]; @@ -125,6 +134,8 @@ class instance_ulduar : public InstanceMapScript KologarnGUID = 0; AuriayaGUID = 0; MimironGUID = 0; + MimironComputerGUID = 0; + MimironWorldTriggerGUID = 0; HodirGUID = 0; ThorimGUID = 0; FreyaGUID = 0; @@ -139,6 +150,9 @@ class instance_ulduar : public InstanceMapScript ThorimChestGUID = 0; HodirRareCacheGUID = 0; HodirChestGUID = 0; + MimironTramGUID = 0; + MimironElevatorGUID = 0; + MimironButtonGUID = 0; LeviathanGateGUID = 0; AlgalonUniverseGUID = 0; AlgalonTrapdoorGUID = 0; @@ -165,6 +179,7 @@ class instance_ulduar : public InstanceMapScript memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs)); memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs)); memset(ElderGUIDs, 0, sizeof(ElderGUIDs)); + memset(MimironVehicleGUIDs, 0, sizeof(MimironVehicleGUIDs)); memset(BrainRoomDoorGUIDs, 0, sizeof(BrainRoomDoorGUIDs)); memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs)); memset(_summonObservationRingKeeper, false, sizeof(_summonObservationRingKeeper)); @@ -288,9 +303,6 @@ class instance_ulduar : public InstanceMapScript case NPC_AURIAYA: AuriayaGUID = creature->GetGUID(); break; - case NPC_MIMIRON: - MimironGUID = creature->GetGUID(); - break; // Hodir case NPC_HODIR: @@ -353,6 +365,28 @@ class instance_ulduar : public InstanceMapScript creature->DespawnOrUnsummon(); break; + // Mimiron + case NPC_MIMIRON: + MimironGUID = creature->GetGUID(); + break; + case NPC_LEVIATHAN_MKII: + MimironVehicleGUIDs[0] = creature->GetGUID(); + if (GetBossState(BOSS_MIMIRON) == DONE) + creature->DespawnOrUnsummon(); + break; + case NPC_VX_001: + MimironVehicleGUIDs[1] = creature->GetGUID(); + break; + case NPC_AERIAL_COMMAND_UNIT: + MimironVehicleGUIDs[2] = creature->GetGUID(); + break; + case NPC_COMPUTER: + MimironComputerGUID = creature->GetGUID(); + break; + case NPC_WORLD_TRIGGER_MIMIRON: + MimironWorldTriggerGUID = creature->GetGUID(); + break; + case NPC_VEZAX: VezaxGUID = creature->GetGUID(); break; @@ -469,6 +503,15 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_CHEST: HodirChestGUID = gameObject->GetGUID(); break; + case GO_MIMIRON_TRAM: + MimironTramGUID = gameObject->GetGUID(); + break; + case GO_MIMIRON_ELEVATOR: + MimironElevatorGUID = gameObject->GetGUID(); + break; + case GO_MIMIRON_BUTTON: + MimironButtonGUID = gameObject->GetGUID(); + break; case GO_LEVIATHAN_GATE: LeviathanGateGUID = gameObject->GetGUID(); if (GetBossState(BOSS_LEVIATHAN) == DONE) @@ -481,6 +524,9 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_ENTRANCE: case GO_HODIR_DOOR: case GO_HODIR_ICE_DOOR: + case GO_MIMIRON_DOOR_1: + case GO_MIMIRON_DOOR_2: + case GO_MIMIRON_DOOR_3: case GO_VEZAX_DOOR: case GO_YOGG_SARON_DOOR: AddDoor(gameObject, true); @@ -565,6 +611,9 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_ENTRANCE: case GO_HODIR_DOOR: case GO_HODIR_ICE_DOOR: + case GO_MIMIRON_DOOR_1: + case GO_MIMIRON_DOOR_2: + case GO_MIMIRON_DOOR_3: case GO_VEZAX_DOOR: case GO_YOGG_SARON_DOOR: case GO_DOODAD_UL_SIGILDOOR_03: @@ -773,6 +822,10 @@ class instance_ulduar : public InstanceMapScript break; case DATA_UNBROKEN: Unbroken = bool(data); + break; + case DATA_MIMIRON_ELEVATOR: + if (GameObject* gameObject = instance->GetGameObject(MimironElevatorGUID)) + gameObject->SetGoState((GOState)data); break; case DATA_ILLUSION: illusion = data; @@ -845,8 +898,6 @@ class instance_ulduar : public InstanceMapScript return KologarnGUID; case BOSS_AURIAYA: return AuriayaGUID; - case BOSS_MIMIRON: - return MimironGUID; case BOSS_HODIR: return HodirGUID; case BOSS_THORIM: @@ -861,6 +912,22 @@ class instance_ulduar : public InstanceMapScript return ElderGUIDs[1]; case BOSS_STONEBARK: return ElderGUIDs[2]; + + // Mimiron + case BOSS_MIMIRON: + return MimironGUID; + case DATA_LEVIATHAN_MK_II: + return MimironVehicleGUIDs[0]; + case DATA_VX_001: + return MimironVehicleGUIDs[1]; + case DATA_AERIAL_COMMAND_UNIT: + return MimironVehicleGUIDs[2]; + case DATA_COMPUTER: + return MimironComputerGUID; + case DATA_MIMIRON_WORLD_TRIGGER: + return MimironWorldTriggerGUID; + case DATA_MIMIRON_BUTTON: + return MimironButtonGUID; case BOSS_VEZAX: return VezaxGUID; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 3544ff3c079..1c9fa7575d0 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -83,6 +83,18 @@ enum UlduarNPCs NPC_LEVIATHAN_MKII = 33432, NPC_VX_001 = 33651, NPC_AERIAL_COMMAND_UNIT = 33670, + NPC_ASSAULT_BOT = 34057, + NPC_BOMB_BOT = 33836, + NPC_JUNK_BOT = 33855, + NPC_EMERGENCY_FIRE_BOT = 34147, + NPC_FROST_BOMB = 34149, + NPC_BURST_TARGET = 34211, + NPC_FLAME = 34363, + NPC_FLAME_SPREAD = 34121, + NPC_DB_TARGET = 33576, + NPC_ROCKET_MIMIRON_VISUAL = 34050, + NPC_WORLD_TRIGGER_MIMIRON = 21252, + NPC_COMPUTER = 34143, // Freya's Keepers NPC_IRONBRANCH = 32913, @@ -204,6 +216,18 @@ enum UlduarGameObjects GO_THORIM_CHEST_HERO = 194315, GO_THORIM_CHEST = 194314, + // Mimiron + GO_MIMIRON_TRAM = 194675, + GO_MIMIRON_ELEVATOR = 194749, + GO_MIMIRON_BUTTON = 194739, + GO_MIMIRON_DOOR_1 = 194774, + GO_MIMIRON_DOOR_2 = 194775, + GO_MIMIRON_DOOR_3 = 194776, + GO_CACHE_OF_INNOVATION = 194789, + GO_CACHE_OF_INNOVATION_FIREFIGHTER = 194957, + GO_CACHE_OF_INNOVATION_HERO = 194956, + GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO = 194958, + // Vezax GO_VEZAX_DOOR = 194750, @@ -292,6 +316,16 @@ enum UlduarData // Hodir DATA_HODIR_RARE_CACHE, + // Mimiron + DATA_LEVIATHAN_MK_II, + DATA_VX_001, + DATA_AERIAL_COMMAND_UNIT, + DATA_COMPUTER, + DATA_MIMIRON_WORLD_TRIGGER, + DATA_MIMIRON_ELEVATOR, + DATA_MIMIRON_TRAM, + DATA_MIMIRON_BUTTON, + // Yogg-Saron DATA_VOICE_OF_YOGG_SARON, DATA_SARA, -- cgit v1.2.3 From 80e0c443fff2baf812d03c18970f591e4abc15f1 Mon Sep 17 00:00:00 2001 From: Kittnz Date: Tue, 24 Jun 2014 18:23:37 +0200 Subject: Quest: Powering our Defenses fixed Fix by @Discover-, @untaught, @Kittnz --- sql/updates/world/2014_06_24_05_world_quest.sql | 2 ++ .../scripts/EasternKingdoms/zone_eversong_woods.cpp | 18 +++++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) create mode 100644 sql/updates/world/2014_06_24_05_world_quest.sql (limited to 'src/server/scripts') diff --git a/sql/updates/world/2014_06_24_05_world_quest.sql b/sql/updates/world/2014_06_24_05_world_quest.sql new file mode 100644 index 00000000000..49431fdf460 --- /dev/null +++ b/sql/updates/world/2014_06_24_05_world_quest.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template` SET `SpecialFlags`=0 WHERE `entry`=8490; diff --git a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp index 8c612a11621..bc4fff4da7b 100644 --- a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp +++ b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp @@ -190,6 +190,9 @@ enum InfusedCrystal // Quest QUEST_POWERING_OUR_DEFENSES = 8490, + // Quest Credit + QUEST_POD_CREDIT = 16364, + // Says EMOTE = 0, @@ -266,24 +269,17 @@ public: summoned->AI()->AttackStart(me); } - void JustDied(Unit* /*killer*/) override - { - if (PlayerGUID && !Completed) - if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) - player->FailQuest(QUEST_POWERING_OUR_DEFENSES); - } - void UpdateAI(uint32 diff) override { if (EndTimer < diff && Progress) { - Talk(EMOTE); Completed = true; if (PlayerGUID) if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) - player->CompleteQuest(QUEST_POWERING_OUR_DEFENSES); - - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + { + Talk(EMOTE, player); + player->KilledMonsterCredit(QUEST_POD_CREDIT); + } me->RemoveCorpse(); } else EndTimer -= diff; -- cgit v1.2.3 From 6ebb64892fa4cbfacd3f3de5dfa1fe36b02f848c Mon Sep 17 00:00:00 2001 From: MitchesD Date: Thu, 26 Jun 2014 21:33:40 +0200 Subject: Scripts/MagistersTerrace: reworked InstanceScript and fixed some issues on boss Vexallus * removed old hacks and added missing auras * Vexallus converted to EventMap --- sql/updates/world/2014_06_26_02_world_misc.sql | 7 + .../MagistersTerrace/boss_felblood_kaelthas.cpp | 8 +- .../MagistersTerrace/boss_priestess_delrissa.cpp | 8 +- .../MagistersTerrace/boss_selin_fireheart.cpp | 8 +- .../MagistersTerrace/boss_vexallus.cpp | 256 ++++++------- .../instance_magisters_terrace.cpp | 424 +++++++++------------ .../MagistersTerrace/magisters_terrace.h | 38 +- 7 files changed, 339 insertions(+), 410 deletions(-) create mode 100644 sql/updates/world/2014_06_26_02_world_misc.sql (limited to 'src/server/scripts') diff --git a/sql/updates/world/2014_06_26_02_world_misc.sql b/sql/updates/world/2014_06_26_02_world_misc.sql new file mode 100644 index 00000000000..dade11c549d --- /dev/null +++ b/sql/updates/world/2014_06_26_02_world_misc.sql @@ -0,0 +1,7 @@ +-- Pure Energy +SET @ENTRY := 24745; +UPDATE `creature_template` SET `flags_extra`=0 WHERE `entry`=@ENTRY; + +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(@ENTRY, 0, 0x0, 0x0, '44326 46156'); diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index 3c4b372808b..7944011c7a0 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -150,14 +150,14 @@ public: Phase = 0; - instance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_KAELTHAS, NOT_STARTED); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - instance->SetData(DATA_KAELTHAS_EVENT, DONE); + instance->SetBossState(DATA_KAELTHAS, DONE); // Enable the Translocation Orb Exit if (GameObject* escapeOrb = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_ESCAPE_ORB))) @@ -172,7 +172,7 @@ public: void EnterCombat(Unit* /*who*/) override { - instance->SetData(DATA_KAELTHAS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); } void MoveInLineOfSight(Unit* who) override @@ -515,7 +515,7 @@ public: return; } //Don't really die in all phases of Kael'Thas - if (instance->GetData(DATA_KAELTHAS_EVENT) == 0) + if (instance->GetBossState(DATA_KAELTHAS) == 0) { //prevent death damage = 0; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp index 8dc8ff799ba..2af9d9b1567 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp @@ -153,7 +153,7 @@ public: //this mean she at some point evaded void JustReachedHome() override { - instance->SetData(DATA_DELRISSA_EVENT, FAIL); + instance->SetBossState(DATA_DELRISSA, FAIL); } void EnterCombat(Unit* who) override @@ -172,7 +172,7 @@ public: } } - instance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_DELRISSA, IN_PROGRESS); } void InitializeLackeys() @@ -240,7 +240,7 @@ public: Talk(SAY_DEATH); if (instance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY) - instance->SetData(DATA_DELRISSA_EVENT, DONE); + instance->SetBossState(DATA_DELRISSA, DONE); else { if (me->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) @@ -434,7 +434,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - instance->SetData(DATA_DELRISSA_EVENT, DONE); + instance->SetBossState(DATA_DELRISSA, DONE); } } } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp index d77f5db9cea..d6c0f95f967 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp @@ -119,7 +119,7 @@ public: } // Set Inst data for encounter - instance->SetData(DATA_SELIN_EVENT, NOT_STARTED); + instance->SetBossState(DATA_SELIN, NOT_STARTED); DrainLifeTimer = urand(3000, 7000); DrainManaTimer = DrainLifeTimer + 5000; @@ -194,7 +194,7 @@ public: void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - instance->SetData(DATA_SELIN_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_SELIN, IN_PROGRESS); } void KilledUnit(Unit* /*victim*/) override @@ -228,7 +228,7 @@ public: { Talk(SAY_DEATH); - instance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete! + instance->SetBossState(DATA_SELIN, DONE); // Encounter complete! ShatterRemainingCrystals(); } @@ -351,7 +351,7 @@ public: } } } - } else TC_LOG_ERROR("scripts", ERROR_INST_DATA); + } } }; }; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp index 58b9ef12095..644f6860241 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -16,13 +15,6 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Boss_Vexallus -SD%Complete: 90 -SDComment: Heroic and Normal support. Needs further testing. -SDCategory: Magister's Terrace -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "magisters_terrace.h" @@ -41,26 +33,22 @@ enum Yells enum Spells { - // Pure energy spell info - SPELL_ENERGY_BOLT = 46156, - SPELL_ENERGY_FEEDBACK = 44335, - - // Vexallus spell info SPELL_CHAIN_LIGHTNING = 44318, - SPELL_H_CHAIN_LIGHTNING = 46380, // heroic spell SPELL_OVERLOAD = 44353, SPELL_ARCANE_SHOCK = 44319, - SPELL_H_ARCANE_SHOCK = 46381, // heroic spell SPELL_SUMMON_PURE_ENERGY = 44322, // mod scale -10 H_SPELL_SUMMON_PURE_ENERGY1 = 46154, // mod scale -5 H_SPELL_SUMMON_PURE_ENERGY2 = 46159 // mod scale -5 - }; -enum Creatures +enum Events { - NPC_PURE_ENERGY = 24745, + EVENT_ENERGY_BOLT = 1, + EVENT_ENERGY_FEEDBACK, + EVENT_CHAIN_LIGHTNING, + EVENT_OVERLOAD, + EVENT_ARCANE_SHOCK }; enum Misc @@ -71,170 +59,160 @@ enum Misc class boss_vexallus : public CreatureScript { -public: - boss_vexallus() : CreatureScript("boss_vexallus") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - }; - - struct boss_vexallusAI : public BossAI - { - boss_vexallusAI(Creature* creature) : BossAI(creature, DATA_VEXALLUS_EVENT) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; + public: + boss_vexallus() : CreatureScript("boss_vexallus") { } - uint32 ChainLightningTimer; - uint32 ArcaneShockTimer; - uint32 OverloadTimer; - uint32 IntervalHealthAmount; - bool Enraged; - - void Reset() override + struct boss_vexallusAI : public BossAI { - summons.DespawnAll(); - ChainLightningTimer = 8000; - ArcaneShockTimer = 5000; - OverloadTimer = 1200; - IntervalHealthAmount = 1; - Enraged = false; - - instance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED); - } + boss_vexallusAI(Creature* creature) : BossAI(creature, DATA_VEXALLUS) + { + _intervalHealthAmount = 1; + _enraged = false; + } - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_KILL); - } + void Reset() override + { + _Reset(); + _intervalHealthAmount = 1; + _enraged = false; + } - void JustDied(Unit* /*killer*/) override - { - summons.DespawnAll(); - instance->SetData(DATA_VEXALLUS_EVENT, DONE); - } + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_KILL); + } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + } - instance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS); - } + void EnterCombat(Unit* /*who*/) override + { + Talk(SAY_AGGRO); + _EnterCombat(); - void JustSummoned(Creature* summoned) override - { - if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 0)) - summoned->GetMotionMaster()->MoveFollow(temp, 0, 0); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 8000); + events.ScheduleEvent(EVENT_ARCANE_SHOCK, 5000); + } - //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok - summoned->CastSpell(summoned, SPELL_ENERGY_BOLT, false, 0, 0, me->GetGUID()); - } + void JustSummoned(Creature* summoned) override + { + if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 0)) + summoned->GetMotionMaster()->MoveFollow(temp, 0, 0); - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + summons.Summon(summoned); + } - if (!Enraged) + void DamageTaken(Unit* /*who*/, uint32& damage) override { - //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25% - if (!HealthAbovePct(100 - INTERVAL_MODIFIER * IntervalHealthAmount)) + if (_enraged) + return; + + // 85%, 70%, 55%, 40%, 25% + if (!HealthAbovePct(100 - INTERVAL_MODIFIER * _intervalHealthAmount)) { - //increase amount, unless we're at 10%, then we switch and return - if (IntervalHealthAmount == INTERVAL_SWITCH) + // increase amount, unless we're at 10%, then we switch and return + if (_intervalHealthAmount == INTERVAL_SWITCH) { - Enraged = true; + _enraged = true; + events.Reset(); + events.ScheduleEvent(EVENT_OVERLOAD, 1200); return; } else - ++IntervalHealthAmount; + ++_intervalHealthAmount; Talk(SAY_ENERGY); Talk(EMOTE_DISCHARGE_ENERGY); if (IsHeroic()) { - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false); - DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false); + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1); + DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2); } else - DoCast(me, SPELL_SUMMON_PURE_ENERGY, false); - - //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (IsHeroic()) - me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoCast(me, SPELL_SUMMON_PURE_ENERGY); } + } - if (ChainLightningTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_CHAIN_LIGHTNING); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - ChainLightningTimer = 8000; - } else ChainLightningTimer -= diff; + events.Update(diff); - if (ArcaneShockTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - if (target) - DoCast(target, SPELL_ARCANE_SHOCK); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - ArcaneShockTimer = 8000; - } else ArcaneShockTimer -= diff; - } - else - { - if (OverloadTimer <= diff) + while (uint32 eventId = events.ExecuteEvent()) { - DoCastVictim(SPELL_OVERLOAD); + switch (eventId) + { + case EVENT_CHAIN_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 8000); + break; + case EVENT_ARCANE_SHOCK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true)) + DoCast(target, SPELL_ARCANE_SHOCK); + events.ScheduleEvent(EVENT_ARCANE_SHOCK, 8000); + break; + case EVENT_OVERLOAD: + DoCastVictim(SPELL_OVERLOAD); + events.ScheduleEvent(EVENT_OVERLOAD, 2000); + break; + default: + break; + } + } - OverloadTimer = 2000; - } else OverloadTimer -= diff; + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + private: + uint32 _intervalHealthAmount; + bool _enraged; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + }; }; -class npc_pure_energy : public CreatureScript +enum NpcPureEnergy { -public: - npc_pure_energy() : CreatureScript("npc_pure_energy") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pure_energyAI(creature); - }; - - struct npc_pure_energyAI : public ScriptedAI - { - npc_pure_energyAI(Creature* creature) : ScriptedAI(creature) - { - me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - } + SPELL_ENERGY_BOLT = 46156, + SPELL_ENERGY_FEEDBACK = 44335, + SPELL_PURE_ENERGY_PASSIVE = 44326 +}; - void Reset() override { } +class npc_pure_energy : public CreatureScript +{ + public: + npc_pure_energy() : CreatureScript("npc_pure_energy") { } - void JustDied(Unit* slayer) override + struct npc_pure_energyAI : public ScriptedAI { - if (Unit* temp = me->GetOwner()) + npc_pure_energyAI(Creature* creature) : ScriptedAI(creature) { - if (temp && temp->IsAlive()) - slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID()); + me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); } - } - void EnterCombat(Unit* /*who*/) override { } - void MoveInLineOfSight(Unit* /*who*/) override { } + void JustDied(Unit* killer) override + { + killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true); + me->RemoveAurasDueToSpell(SPELL_PURE_ENERGY_PASSIVE); + } + }; - void AttackStart(Unit* /*who*/) override { } - }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_pure_energyAI(creature); + }; }; void AddSC_boss_vexallus() diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index daea647609d..cce83a8d7ee 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -16,19 +15,10 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Instance_Magisters_Terrace -SD%Complete: 60 -SDComment: Designed only for Selin Fireheart -SDCategory: Magister's Terrace -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "magisters_terrace.h" -#define MAX_ENCOUNTER 4 - /* 0 - Selin Fireheart 1 - Vexallus @@ -36,281 +26,223 @@ EndScriptData */ 3 - Kael'thas Sunstrider */ -enum Creatures +DoorData const doorData[] = { - NPC_SELIN = 24723, - NPC_DELRISSA = 24560, - NPC_FELCRYSTALS = 24722 -}; - -enum GameObjects -{ - GO_VEXALLUS_DOOR = 187896, - GO_SELIN_DOOR = 187979, - GO_SELIN_ENCOUNTER_DOOR = 188065, - GO_DELRISSA_DOOR = 187770, - GO_KAEL_DOOR = 188064, - GO_KAEL_STATUE_1 = 188165, - GO_KAEL_STATUE_2 = 188166, - GO_ESCAPE_ORB = 188173 + { GO_SELIN_DOOR, DATA_SELIN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_SELIN_ENCOUNTER_DOOR, DATA_SELIN, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_VEXALLUS_DOOR, DATA_VEXALLUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_DELRISSA_DOOR, DATA_DELRISSA, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_KAEL_DOOR, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END }; class instance_magisters_terrace : public InstanceMapScript { -public: - instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace", 585) { } - - struct instance_magisters_terrace_InstanceMapScript : public InstanceScript - { - instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map) { } - - uint32 Encounter[MAX_ENCOUNTER]; - uint32 DelrissaDeathCount; + public: + instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace", 585) { } - std::vector FelCrystals; - - uint64 SelinGUID; - uint64 DelrissaGUID; - uint64 VexallusDoorGUID; - uint64 SelinDoorGUID; - uint64 SelinEncounterDoorGUID; - uint64 DelrissaDoorGUID; - uint64 KaelDoorGUID; - uint64 KaelStatue[2]; - uint64 EscapeOrbGUID; - uint32 StatuesState; - uint8 felCristalIndex; - - void Initialize() override + struct instance_magisters_terrace_InstanceMapScript : public InstanceScript { - memset(&Encounter, 0, sizeof(Encounter)); - - FelCrystals.clear(); + instance_magisters_terrace_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); - DelrissaDeathCount = 0; + FelCrystals.clear(); + DelrissaDeathCount = 0; - SelinGUID = 0; - DelrissaGUID = 0; - VexallusDoorGUID = 0; - SelinDoorGUID = 0; - SelinEncounterDoorGUID = 0; - DelrissaDoorGUID = 0; - KaelDoorGUID = 0; - KaelStatue[0] = 0; - KaelStatue[1] = 0; - EscapeOrbGUID = 0; - StatuesState = 0; - felCristalIndex = 0; - } + SelinGUID = 0; + DelrissaGUID = 0; + EscapeOrbGUID = 0; + FelCristalIndex = 0; - bool IsEncounterInProgress() const override - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (Encounter[i] == IN_PROGRESS) - return true; - return false; - } + memset(KaelStatue, 0, 2 * sizeof(uint64)); + } - uint32 GetData(uint32 identifier) const - { - switch (identifier) + uint32 GetData(uint32 type) const override { - case DATA_SELIN_EVENT: - return Encounter[0]; - case DATA_VEXALLUS_EVENT: - return Encounter[1]; - case DATA_DELRISSA_EVENT: - return Encounter[2]; - case DATA_KAELTHAS_EVENT: - return Encounter[3]; - case DATA_DELRISSA_DEATH_COUNT: - return DelrissaDeathCount; - case DATA_FEL_CRYSTAL_SIZE: - return FelCrystals.size(); + switch (type) + { + case DATA_DELRISSA_DEATH_COUNT: + return DelrissaDeathCount; + case DATA_FEL_CRYSTAL_SIZE: + return FelCrystals.size(); + default: + break; + } + return 0; } - return 0; - } - void SetData(uint32 identifier, uint32 data) - { - switch (identifier) + void SetData(uint32 type, uint32 data) override { - case DATA_SELIN_EVENT: - if (data == DONE) - { - HandleGameObject(SelinEncounterDoorGUID, true); - HandleGameObject(SelinDoorGUID, true); - } - else if (data == IN_PROGRESS) - HandleGameObject(SelinEncounterDoorGUID, false); - else if (data == NOT_STARTED) - HandleGameObject(SelinEncounterDoorGUID, true); - - Encounter[0] = data; - break; - case DATA_VEXALLUS_EVENT: - if (data == DONE) - HandleGameObject(VexallusDoorGUID, true); - Encounter[1] = data; - break; - case DATA_DELRISSA_EVENT: - if (data == DONE) - HandleGameObject(DelrissaDoorGUID, true); - if (data == IN_PROGRESS) - DelrissaDeathCount = 0; - Encounter[2] = data; - break; - case DATA_KAELTHAS_EVENT: - if (data == NOT_STARTED || data == DONE) - HandleGameObject(KaelDoorGUID, true); - else if (data == IN_PROGRESS) - HandleGameObject(KaelDoorGUID, false); - Encounter[3] = data; - break; - case DATA_DELRISSA_DEATH_COUNT: - if (data == SPECIAL) - ++DelrissaDeathCount; - else - DelrissaDeathCount = 0; - break; - case DATA_KAELTHAS_STATUES: - HandleGameObject(KaelStatue[0], data); - HandleGameObject(KaelStatue[1], data); - StatuesState = data; - break; + switch (type) + { + case DATA_DELRISSA_DEATH_COUNT: + if (data == SPECIAL) + ++DelrissaDeathCount; + else + DelrissaDeathCount = 0; + break; + case DATA_KAELTHAS_STATUES: + HandleGameObject(KaelStatue[0], data); + HandleGameObject(KaelStatue[1], data); + break; + default: + break; + } } - SaveToDB(); - } - - void OnCreatureCreate(Creature* creature) override - { - switch (creature->GetEntry()) + void OnCreatureCreate(Creature* creature) override { - case NPC_SELIN: - SelinGUID = creature->GetGUID(); - break; - case NPC_DELRISSA: - DelrissaGUID = creature->GetGUID(); - break; - case NPC_FELCRYSTALS: - FelCrystals.push_back(creature->GetGUID()); - break; + switch (creature->GetEntry()) + { + case NPC_SELIN: + SelinGUID = creature->GetGUID(); + break; + case NPC_DELRISSA: + DelrissaGUID = creature->GetGUID(); + break; + case NPC_FELCRYSTALS: + FelCrystals.push_back(creature->GetGUID()); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) + void OnGameObjectCreate(GameObject* go) override { - case GO_VEXALLUS_DOOR: - VexallusDoorGUID = go->GetGUID(); - break; - case GO_SELIN_DOOR: - SelinDoorGUID = go->GetGUID(); - break; - case GO_SELIN_ENCOUNTER_DOOR: - SelinEncounterDoorGUID = go->GetGUID(); - break; - case GO_DELRISSA_DOOR: - DelrissaDoorGUID = go->GetGUID(); - break; - case GO_KAEL_DOOR: - KaelDoorGUID = go->GetGUID(); - break; - case GO_KAEL_STATUE_1: - KaelStatue[0] = go->GetGUID(); - break; - case GO_KAEL_STATUE_2: - KaelStatue[1] = go->GetGUID(); - break; - case GO_ESCAPE_ORB: - EscapeOrbGUID = go->GetGUID(); - break; + switch (go->GetEntry()) + { + case GO_VEXALLUS_DOOR: + case GO_SELIN_DOOR: + case GO_SELIN_ENCOUNTER_DOOR: + case GO_DELRISSA_DOOR: + case GO_KAEL_DOOR: + AddDoor(go, true); + break; + case GO_KAEL_STATUE_1: + KaelStatue[0] = go->GetGUID(); + break; + case GO_KAEL_STATUE_2: + KaelStatue[1] = go->GetGUID(); + break; + case GO_ESCAPE_ORB: + EscapeOrbGUID = go->GetGUID(); + break; + default: + break; + } } - } - - std::string GetSaveData() override - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << Encounter[0] << ' ' << Encounter[1] << ' ' << Encounter[2] << ' ' << Encounter[3] << ' ' << StatuesState; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - void Load(const char* str) override - { - if (!str) + bool SetBossState(uint32 type, EncounterState state) override { - OUT_LOAD_INST_DATA_FAIL; - return; + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_DELRISSA: + if (type == IN_PROGRESS) + DelrissaDeathCount = 0; + break; + default: + break; + } + return true; } - OUT_LOAD_INST_DATA(str); + std::string GetSaveData() override + { + OUT_SAVE_INST_DATA; - std::istringstream loadStream(str); + std::ostringstream saveStream; + saveStream << "M T " << GetBossSaveData(); - for (uint32 i = 0; i < MAX_ENCOUNTER; ++i) - { - uint32 tmpState; - loadStream >> tmpState; - if (tmpState == IN_PROGRESS || tmpState > SPECIAL) - tmpState = NOT_STARTED; - SetData(i, tmpState); + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - loadStream >> StatuesState; - SetData(DATA_KAELTHAS_STATUES, StatuesState); + void Load(const char* str) override + { + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - OUT_LOAD_INST_DATA_COMPLETE; - } + OUT_LOAD_INST_DATA(str); - uint64 GetData64(uint32 identifier) const - { - switch (identifier) - { - case DATA_SELIN: - return SelinGUID; - case DATA_DELRISSA: - return DelrissaGUID; - case DATA_VEXALLUS_DOOR: - return VexallusDoorGUID; - case DATA_DELRISSA_DOOR: - return DelrissaDoorGUID; - case DATA_KAEL_DOOR: - return KaelDoorGUID; - case DATA_KAEL_STATUE_LEFT: - return KaelStatue[0]; - case DATA_KAEL_STATUE_RIGHT: - return KaelStatue[1]; - case DATA_ESCAPE_ORB: - return EscapeOrbGUID; - case DATA_FEL_CRYSTAL: - if (FelCrystals.size() < felCristalIndex) + char dataHead1, dataHead2; + + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + if (dataHead1 == 'M' && dataHead2 == 'T') + { + for (uint32 i = 0; i < EncounterCount; ++i) { - TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data"); - return 0; + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); } + } + else + OUT_LOAD_INST_DATA_FAIL; - return FelCrystals.at(felCristalIndex); + OUT_LOAD_INST_DATA_COMPLETE; + } + + uint64 GetData64(uint32 type) const override + { + switch (type) + { + case DATA_SELIN: + return SelinGUID; + case DATA_DELRISSA: + return DelrissaGUID; + case DATA_KAEL_STATUE_LEFT: + return KaelStatue[0]; + case DATA_KAEL_STATUE_RIGHT: + return KaelStatue[1]; + case DATA_ESCAPE_ORB: + return EscapeOrbGUID; + case DATA_FEL_CRYSTAL: + if (FelCrystals.size() < FelCristalIndex) + { + TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data"); + return 0; + } + + return FelCrystals.at(FelCristalIndex); + default: + break; + } + return 0; } - return 0; - } - void SetData64(uint32 identifier, uint64 value) + void SetData64(uint32 type, uint64 value) override + { + if (type == DATA_FEL_CRYSTAL) + FelCristalIndex = value; + } + + protected: + std::vector FelCrystals; + + uint64 SelinGUID; + uint64 DelrissaGUID; + uint64 KaelStatue[2]; + uint64 EscapeOrbGUID; + uint32 DelrissaDeathCount; + uint8 FelCristalIndex; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override { - if (identifier == DATA_FEL_CRYSTAL) - felCristalIndex = value; + return new instance_magisters_terrace_InstanceMapScript(map); } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const override - { - return new instance_magisters_terrace_InstanceMapScript(map); - } }; void AddSC_instance_magisters_terrace() diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h index ddfaa91bc98..d3517dfccf6 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h @@ -19,24 +19,17 @@ #ifndef DEF_MAGISTERS_TERRACE_H #define DEF_MAGISTERS_TERRACE_H -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy." +uint32 const EncounterCount = 4; -enum Data +enum DataTypes { - DATA_SELIN_EVENT, - DATA_VEXALLUS_EVENT, - DATA_DELRISSA_EVENT, - DATA_KAELTHAS_EVENT, - DATA_SELIN, - DATA_FEL_CRYSTAL, - DATA_FEL_CRYSTAL_SIZE, - - DATA_VEXALLUS_DOOR, + DATA_VEXALLUS, DATA_DELRISSA, - DATA_DELRISSA_DOOR, + DATA_KAELTHAS, - DATA_KAEL_DOOR, + DATA_FEL_CRYSTAL, + DATA_FEL_CRYSTAL_SIZE, DATA_KAEL_STATUE_LEFT, DATA_KAEL_STATUE_RIGHT, @@ -45,4 +38,23 @@ enum Data DATA_ESCAPE_ORB }; +enum CreatureIds +{ + NPC_SELIN = 24723, + NPC_DELRISSA = 24560, + NPC_FELCRYSTALS = 24722 +}; + +enum GameObjectIds +{ + GO_VEXALLUS_DOOR = 187896, + GO_SELIN_DOOR = 187979, + GO_SELIN_ENCOUNTER_DOOR = 188065, + GO_DELRISSA_DOOR = 187770, + GO_KAEL_DOOR = 188064, + GO_KAEL_STATUE_1 = 188165, + GO_KAEL_STATUE_2 = 188166, + GO_ESCAPE_ORB = 188173 +}; + #endif -- cgit v1.2.3 From 27f28552489bab153d5c4717ce48e31496b4c43f Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Thu, 26 Jun 2014 22:50:06 +0200 Subject: Core: Fix warnings and kill again whitespace ... --- src/server/game/Handlers/CharacterHandler.cpp | 4 ++-- src/server/game/World/World.cpp | 2 +- src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp | 2 +- .../EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp | 2 +- src/server/worldserver/worldserver.conf.dist | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index c2f93190a05..9ad382b4686 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -750,9 +750,9 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) std::string IP_str = GetRemoteAddress(); TC_LOG_INFO("entities.player.character", "Account: %d, IP: %s deleted character: %s, GUID: %u, Level: %u", accountId, IP_str.c_str(), name.c_str(), GUID_LOPART(guid), level); - + // To prevent hook failure, place hook before removing reference from DB - sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete. + sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete. // Shouldn't interfere with character deletion though if (sLog->ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) // optimize GetPlayerDump call diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 62603cce950..78470d4e790 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1256,7 +1256,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635); m_bool_configs[CONFIG_IP_BASED_ACTION_LOGGING] = sConfigMgr->GetBoolDefault("Allow.IP.Based.Action.Logging", false); - + m_bool_configs[CONFIG_IP_BASED_LOGIN_LOGGING] = sConfigMgr->GetBoolDefault("Wrong.Password.Login.Logging", false); // call ScriptMgr if we're reloading the configuration diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp index 644f6860241..b9930820303 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp @@ -104,7 +104,7 @@ class boss_vexallus : public CreatureScript summons.Summon(summoned); } - void DamageTaken(Unit* /*who*/, uint32& damage) override + void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override { if (_enraged) return; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index cce83a8d7ee..620249e70c0 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -229,7 +229,7 @@ class instance_magisters_terrace : public InstanceMapScript } protected: - std::vector FelCrystals; + std::vector FelCrystals; uint64 SelinGUID; uint64 DelrissaGUID; diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 5a3ea2bb4e1..90f330bac42 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1354,7 +1354,7 @@ Rate.Creature.Elite.WORLDBOSS.HP = 1 # # Creature.PickPocketRefillDelay -# Description: Time in seconds that the server will wait before refilling the pickpocket loot +# Description: Time in seconds that the server will wait before refilling the pickpocket loot # for a creature # Default: 600 -- cgit v1.2.3 From f94fe58f78c430bbe3a3299aba0729df4b275670 Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Thu, 26 Jun 2014 23:15:53 +0200 Subject: Script/MagistersTerrace: Fix fail in 27f28552489bab153d5c4717ce48e31496b4c43f --- .../EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index 620249e70c0..2ab51dbc6be 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -66,7 +66,7 @@ class instance_magisters_terrace : public InstanceMapScript case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount; case DATA_FEL_CRYSTAL_SIZE: - return FelCrystals.size(); + return uint32(FelCrystals.size()); default: break; } @@ -229,7 +229,7 @@ class instance_magisters_terrace : public InstanceMapScript } protected: - std::vector FelCrystals; + std::vector FelCrystals; uint64 SelinGUID; uint64 DelrissaGUID; -- cgit v1.2.3 From 0a641bace9198f49c82ac1e0276a33d893e990ea Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Fri, 27 Jun 2014 00:40:59 +0100 Subject: Core/Spells: Ensure Haunt's healing takes in consideration crit damage --- src/server/scripts/Spells/spell_warlock.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 3f935077b22..4571798506e 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -518,7 +518,7 @@ class spell_warl_haunt : public SpellScriptLoader { PrepareSpellScript(spell_warl_haunt_SpellScript); - void HandleOnHit() + void HandleAfterHit() { if (Aura* aura = GetHitAura()) if (AuraEffect* aurEff = aura->GetEffect(EFFECT_1)) @@ -527,7 +527,7 @@ class spell_warl_haunt : public SpellScriptLoader void Register() override { - OnHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleOnHit); + AfterHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleAfterHit); } }; -- cgit v1.2.3 From 52023b1e6b1fefaf4be95fa201fc1dd2ecca55a7 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Fri, 27 Jun 2014 18:45:49 +0200 Subject: Scripts/MagistersTerrace: fix possible crash --- .../MagistersTerrace/instance_magisters_terrace.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/server/scripts') diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp index 2ab51dbc6be..e0050420a08 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp @@ -135,6 +135,22 @@ class instance_magisters_terrace : public InstanceMapScript } } + void OnGameObjectRemove(GameObject* go) override + { + switch (go->GetEntry()) + { + case GO_VEXALLUS_DOOR: + case GO_SELIN_DOOR: + case GO_SELIN_ENCOUNTER_DOOR: + case GO_DELRISSA_DOOR: + case GO_KAEL_DOOR: + AddDoor(go, false); + break; + default: + break; + } + } + bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) -- cgit v1.2.3 From d20a5f3df080ce44d547ee98bca875e01598cd64 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sat, 28 Jun 2014 00:57:44 +0200 Subject: Scripts/Commands: fixed possible client crash with .go command --- src/server/game/Globals/ObjectMgr.cpp | 4 ++-- src/server/game/Globals/ObjectMgr.h | 2 ++ src/server/scripts/Commands/cs_go.cpp | 32 ++++++++++++++++++++------------ 3 files changed, 24 insertions(+), 14 deletions(-) (limited to 'src/server/scripts') diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 72ea1b16864..9eb7d5ec1bf 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1668,7 +1668,7 @@ void ObjectMgr::LoadCreatures() } // Skip spawnMask check for transport maps - if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) + if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid); bool ok = true; @@ -2003,7 +2003,7 @@ void ObjectMgr::LoadGameobjects() data.spawnMask = fields[14].GetUInt8(); - if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) + if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); data.phaseMask = fields[15].GetUInt32(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index ba5940d7e12..e5e55b847d3 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1293,6 +1293,8 @@ class ObjectMgr void LoadFactionChangeSpells(); void LoadFactionChangeTitles(); + bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId); } + private: // first free id for selected id type uint32 _auctionId; diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 3c1fa973cd8..44ebb1ea4e0 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -29,6 +29,7 @@ EndScriptData */ #include "Chat.h" #include "Language.h" #include "Player.h" +#include "Transport.h" class go_commandscript : public CommandScript { @@ -132,21 +133,24 @@ public: float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); - float ort = fields[3].GetFloat(); - int mapId = fields[4].GetUInt16(); + float o = fields[3].GetFloat(); + uint32 mapId = fields[4].GetUInt16(); uint32 guid = fields[5].GetUInt32(); uint32 id = fields[6].GetUInt32(); - // if creature is in same map with caster go at its current location - if (Creature* creature = sObjectAccessor->GetCreature(*player, MAKE_NEW_GUID(guid, id, HIGHGUID_UNIT))) + Transport* transport = NULL; + + if (Creature* creature = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(guid, id, HIGHGUID_UNIT), (Creature*)NULL)) { x = creature->GetPositionX(); y = creature->GetPositionY(); z = creature->GetPositionZ(); - ort = creature->GetOrientation(); + o = creature->GetOrientation(); + mapId = creature->GetMapId(); + transport = creature->GetTransport(); } - if (!MapManager::IsValidMapCoord(mapId, x, y, z, ort)) + if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId)) { handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); handler->SetSentErrorMessage(true); @@ -163,7 +167,11 @@ public: else player->SaveRecallPosition(); - player->TeleportTo(mapId, x, y, z, ort); + if (player->TeleportTo(mapId, x, y, z, o)) + { + if (transport) + transport->AddPassenger(player); + } return true; } @@ -274,8 +282,8 @@ public: if (!guid) return false; - float x, y, z, ort; - int mapId; + float x, y, z, o; + uint32 mapId; // by DB guid if (GameObjectData const* goData = sObjectMgr->GetGOData(guid)) @@ -283,7 +291,7 @@ public: x = goData->posX; y = goData->posY; z = goData->posZ; - ort = goData->orientation; + o = goData->orientation; mapId = goData->mapid; } else @@ -293,7 +301,7 @@ public: return false; } - if (!MapManager::IsValidMapCoord(mapId, x, y, z, ort)) + if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId)) { handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); handler->SetSentErrorMessage(true); @@ -310,7 +318,7 @@ public: else player->SaveRecallPosition(); - player->TeleportTo(mapId, x, y, z, ort); + player->TeleportTo(mapId, x, y, z, o); return true; } -- cgit v1.2.3 From 1bd4ff6cb94aa2a1dd44931664947bfb4b4887a5 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Sat, 28 Jun 2014 13:49:34 +0200 Subject: Revert "Scripts/Ulduar: Implement Mimiron" --- sql/updates/world/2014_06_12_02_world_misc.sql | 197 -- src/server/game/Spells/SpellMgr.cpp | 10 - .../Northrend/Ulduar/Ulduar/boss_mimiron.cpp | 2937 +------------------- .../Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 79 +- .../scripts/Northrend/Ulduar/Ulduar/ulduar.h | 34 - 5 files changed, 47 insertions(+), 3210 deletions(-) delete mode 100644 sql/updates/world/2014_06_12_02_world_misc.sql (limited to 'src/server/scripts') diff --git a/sql/updates/world/2014_06_12_02_world_misc.sql b/sql/updates/world/2014_06_12_02_world_misc.sql deleted file mode 100644 index da40f46d690..00000000000 --- a/sql/updates/world/2014_06_12_02_world_misc.sql +++ /dev/null @@ -1,197 +0,0 @@ --- -DELETE FROM `vehicle_template_accessory` WHERE `entry` IN (33651, 33432); -INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`) VALUES -(33651, 34050, 5, 1, 'VX-001 Rocket Seat 6', 8), -(33651, 34050, 6, 1, 'VX-001 Rocket Seat 7', 8), -(33432, 34071, 3, 1, 'MKII MKII turret Seat 1', 8); - -DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (33651, 33432); -INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES -(33651, 46598, 1, 1), -(33432, 46598, 1, 1); - -DELETE FROM `spell_script_names` WHERE `spell_id` IN (63274, 63414, 63667, 63382, 64402, 65034, 63681, 64542, 65192, 64570, 63027, 65346, 66351, 65224, 63009, 64620, 63820, 64425, 64426, 64621, 64398, 64567, 64619, 64623, 64627, 65354, 64626, 64618, 65333, 64436, 63340, 64383, 63339, 64562, 63041, 63801, 64463); -INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES -(63801, 'spell_mimiron_bomb_bot'), -(65192, 'spell_mimiron_clear_fires'), -(65224, 'spell_mimiron_clear_fires'), -(64619, 'spell_mimiron_clear_fires'), -(65354, 'spell_mimiron_clear_fires'), -(64463, 'spell_mimiron_despawn_assault_bots'), -(64618, 'spell_mimiron_fire_search'), -(64570, 'spell_mimiron_flame_suppressant'), -(64626, 'spell_mimiron_frost_bomb_explosion'), -(65333, 'spell_mimiron_frost_bomb_explosion'), -(64436, 'spell_mimiron_magnetic_core'), -(63667, 'spell_mimiron_napalm_shell'), -(63274, 'spell_mimiron_p3wx2_laser_barrage'), -(64542, 'spell_mimiron_plasma_blast'), -(63027, 'spell_mimiron_proximity_mines'), -(66351, 'spell_mimiron_proximity_explosion'), -(63009, 'spell_mimiron_proximity_explosion'), -(65346, 'spell_mimiron_proximity_trigger'), -(63382, 'spell_mimiron_rapid_burst'), -(64402, 'spell_mimiron_rocket_strike'), -(65034, 'spell_mimiron_rocket_strike'), -(63041, 'spell_mimiron_rocket_strike_damage'), -(63681, 'spell_mimiron_rocket_strike_target_select'), -(64383, 'spell_mimiron_self_repair'), -(63414, 'spell_mimiron_spinning_up'), -(64426, 'spell_mimiron_summon_assault_bot'), -(64425, 'spell_mimiron_summon_assault_bot_target'), -(64621, 'spell_mimiron_summon_fire_bot'), -(64620, 'spell_mimiron_summon_fire_bot_target'), -(64567, 'spell_mimiron_summon_flames_initial'), -(64562, 'spell_mimiron_summon_flames_spread'), -(64627, 'spell_mimiron_summon_frost_bomb'), -(64623, 'spell_mimiron_summon_frost_bomb_target'), -(64398, 'spell_mimiron_summon_junk_bot'), -(63820, 'spell_mimiron_summon_junk_bot_target'), -(63339, 'spell_mimiron_weld'); - -DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (66351, 64019, 63387, 62997, 64348, 64352, 63689, 65647, 63677, 63679, 64626); -INSERT INTO `spelldifficulty_dbc` (`id`, `spellid0`, `spellid1`) VALUES -(64348, 64348, 64536), -(64352, 64352, 64537), -(66351, 66351, 63009), -(63387, 63387, 64531), -(64019, 64019, 64532), -(62997, 62997, 64529), -(63689, 63689, 64535), -(65647, 65647, 65648), -(63677, 63677, 64533), -(63679, 63679, 64534), -(64626, 64626, 65333); - -DELETE FROM `conditions` WHERE `SourceEntry` IN (65192, 64570, 63274, 66490, 63300, 63414, 64539, 64402, 65034, 63041, 65224, 64620, 63820, 64425, 64619, 64626, 65333, 65354, 64618, 64623, 64436, 64444, 65101, 64463); -INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES -(13, 1, 65192, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Flame Suppressant VX EFFECT_0 can only hit NPC_FLAME'), -(13, 1, 65192, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Flame Suppressant VX EFFECT_0 can only hit NPC_FLAME_SPREAD'), -(13, 2, 64570, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Flame Suppressant MK EFFECT_1 can only hit NPC_FLAME'), -(13, 2, 64570, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Flame Suppressant MK EFFECT_1 can only hit NPC_FLAME_SPREAD'), -(13, 1, 64623, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Frost Bomb EFFECT_0 can only hit NPC_FLAME'), -(13, 1, 64623, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Frost Bomb EFFECT_0 can only hit NPC_FLAME_SPREAD'), -(13, 4, 64626, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Explosion EFFECT_2 can only hit NPC_FLAME'), -(13, 4, 64626, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Explosion EFFECT_2 can only hit NPC_FLAME_SPREAD'), -(13, 4, 65333, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Explosion EFFECT_2 can only hit NPC_FLAME'), -(13, 4, 65333, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Explosion EFFECT_2 can only hit NPC_FLAME_SPREAD'), -(13, 1, 65224, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Clear Fires EFFECT_0 can only hit NPC_FLAME'), -(13, 1, 65224, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Clear Fires EFFECT_0 can only hit NPC_FLAME_SPREAD'), -(13, 1, 65354, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Clear Fires EFFECT_0 can only hit NPC_FLAME'), -(13, 1, 65354, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Clear Fires EFFECT_0 can only hit NPC_FLAME_SPREAD'), -(13, 1, 64619, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Water Spray EFFECT_0 can only hit NPC_FLAME'), -(13, 1, 64619, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Water Spray EFFECT_0 can only hit NPC_FLAME_SPREAD'), -(13, 1, 64618, 0, 0, 31, 0, 3, 34363, 0, 0, 0, 0, '', 'Fire Search EFFECT_0 can only hit NPC_FLAME'), -(13, 1, 64618, 0, 1, 31, 0, 3, 34121, 0, 0, 0, 0, '', 'Fire Search EFFECT_0 can only hit NPC_FLAME_SPREAD'), -(13, 1, 64539, 0, 0, 31, 0, 3, 34071, 0, 0, 0, 0, '', 'Napalm Shell EFFECT_0 can only hit NPC_LEVIATHAN_MKII_TURRET'), -(13, 1, 63274, 0, 0, 31, 0, 3, 33576, 0, 0, 0, 0, '', 'P3Wx2 Laser Barrage EFFECT_0 can only hit NPC_DB_TARGET'), -(17, 0, 66490, 0, 0, 31, 0, 3, 33432, 0, 0, 0, 0, '', 'P3Wx2 Laser Barrage can only hit NPC_LEVIATHAN_MKII'), -(17, 0, 63300, 0, 0, 31, 0, 3, 33651, 0, 0, 0, 0, '', 'P3Wx2 Laser Barrage can only hit NPC_VX_001'), -(13, 1, 63414, 0, 0, 31, 0, 3, 33576, 0, 0, 0, 0, '', 'Spinning Up EFFECT_0 can only hit NPC_DB_TARGET'), -(13, 2, 63414, 0, 1, 31, 0, 3, 33432, 0, 0, 0, 0, '', 'Spinning Up EFFECT_1 can only hit NPC_LEVIATHAN_MKII'), -(13, 1, 64620, 0, 0, 31, 0, 3, 33856, 0, 0, 0, 0, '', 'Summon Fire Bot Trigger EFFECT_0 can only hit NPC_BOT_SUMMON_TRIGGER'), -(13, 1, 63820, 0, 0, 31, 0, 3, 33856, 0, 0, 0, 0, '', 'Summon Junk Bot Trigger EFFECT_0 can only hit NPC_BOT_SUMMON_TRIGGER'), -(13, 1, 64425, 0, 0, 31, 0, 3, 33856, 0, 0, 0, 0, '', 'Summon Assault Bot Trigger EFFECT_0 can only hit NPC_BOT_SUMMON_TRIGGER'), -(13, 1, 64402, 0, 0, 31, 0, 3, 34050, 0, 0, 0, 0, '', 'Rocket Strike EFFECT_0 can only hit NPC_ROCKET_MIMIRON_VISUAL'), -(13, 1, 65034, 0, 0, 31, 0, 3, 34050, 0, 0, 0, 0, '', 'Rocket Strike EFFECT_0 can only hit NPC_ROCKET_MIMIRON_VISUAL'), -(13, 2, 64436, 0, 0, 31, 0, 3, 33670, 0, 0, 0, 0, '', 'Magnetic Core EFFECT_1 can only hit NPC_AERIAL_COMMAND_UNIT'), -(13, 1, 64444, 0, 0, 31, 0, 3, 33670, 0, 0, 0, 0, '', 'Magnetic Core EFFECT_0 can only hit NPC_AERIAL_COMMAND_UNIT'), -(13, 1, 65101, 0, 0, 31, 0, 3, 34071, 0, 0, 0, 0, '', 'Emergency Mode EFFECT_0 can only hit NPC_LEVIATHAN_MKII_TURRET'), -(13, 1, 64463, 0, 0, 31, 0, 3, 34057, 0, 0, 0, 0, '', 'Despawn Assault Bots EFFECT_1 can only hit NPC_ASSAULT_BOT'), -(13, 2, 63041, 0, 0, 31, 0, 3, 34057, 0, 0, 0, 0, '', 'Rocket Strike EFFECT_1 can only hit NPC_ASSAULT_BOT'), -(13, 4, 63041, 0, 1, 31, 0, 3, 34137, 0, 0, 0, 0, '', 'Rocket Strike EFFECT_2 can only hit NPC_EMERGENCY_FIRE_BOT'), -(13, 4, 63041, 0, 2, 31, 0, 3, 33855, 0, 0, 0, 0, '', 'Rocket Strike EFFECT_2 can only hit NPC_JUNK_BOT'), -(13, 4, 63041, 0, 3, 31, 0, 3, 33836, 0, 0, 0, 0, '', 'Rocket Strike EFFECT_2 can only hit NPC_BOMB_BOT'); - -UPDATE `creature_template` SET `HoverHeight` = 15, `ScriptName` = 'boss_aerial_command_unit', `InhabitType` = 3, `mechanic_immune_mask` = 646135679 WHERE `entry` = 33670; -UPDATE `creature_template` SET `HoverHeight` = 15, `InhabitType` = 3, `mechanic_immune_mask` = 646135679 WHERE `entry` = 34109; -UPDATE `creature_template` SET `unit_flags` = 33554438, `ScriptName` = 'boss_vx_001', `mechanic_immune_mask` = 646135679 WHERE `entry` = 33651; -UPDATE `creature_template` SET `unit_flags` = 33554438, `mechanic_immune_mask` = 646135679 WHERE `entry` = 34108; -UPDATE `creature_template` SET `ScriptName` = 'boss_leviathan_mk_ii', `mechanic_immune_mask` = 646135679 WHERE `entry` = 33432; -UPDATE `creature_template` SET `mechanic_immune_mask` = 646135679 WHERE `entry` = 34106; -UPDATE `creature_template` SET `ScriptName` = 'boss_mimiron' WHERE `entry` = 33350; -UPDATE `creature_template` SET `unit_flags` = 131078, `ScriptName` = 'npc_mimiron_proximity_mine' WHERE `entry` = 34362; -UPDATE `creature_template` SET `unit_flags` = 33685510, `faction` = 14, `ScriptName` = 'npc_mimiron_frost_bomb' WHERE `entry` = 34149; -UPDATE `creature_template` SET `unit_flags` = 33685510 WHERE `entry` IN( 34047, 34110, 34050, 34071); -UPDATE `creature_template` SET `unit_flags` = 33685510, `ScriptName` = 'npc_magnetic_core' WHERE `entry` = 34068; -UPDATE `creature_template` SET `unit_flags` = 33554436, `ScriptName` = 'npc_mimiron_flames' WHERE `entry` IN (34363, 34121); -UPDATE `creature_template` SET `faction` = 14 , `ScriptName` = 'npc_mimiron_emergency_fire_bot' WHERE `entry` = 34147; -UPDATE `creature_template` SET `faction` = 14 WHERE `entry` IN (34148, 34114, 33855); -UPDATE `creature_template` SET `dmg_multiplier` = 60, `ScriptName` = 'npc_mimiron_assault_bot' WHERE `entry` = 34057; -UPDATE `creature_template` SET `dmg_multiplier` = 75 WHERE `entry` = 34115; -UPDATE `creature_template` SET `ScriptName` = 'npc_mimiron_computer' WHERE `entry` = 34143; -UPDATE `creature_template` SET `speed_walk` = 2.5 , `speed_run` = 4.5 , `MovementType` = 2 , `InhabitType` = 7, `flags_extra` = 2 WHERE `entry` = 33576; - -UPDATE `creature_model_info` SET `bounding_radius` = 0.31 , `combat_reach` = 5 WHERE `modelid` = 28979; -UPDATE `creature_model_info` SET `bounding_radius` = 0.306 , `combat_reach` = 7 WHERE `modelid` = 28841; -UPDATE `creature_model_info` SET `bounding_radius` = 0.31 , `combat_reach` = 7.7 WHERE `modelid` = 28831; - -UPDATE `gameobject_template` SET `flags` = 32, `ScriptName` = 'go_mimiron_hardmode_button' WHERE `entry` = 194739; - -UPDATE `creature_addon` SET `path_id` = 1376200 WHERE `guid` = 137620; - -UPDATE `creature` SET `position_x` = 2785.423 , `position_y` = 2673.119, `MovementType` = 2 WHERE `guid` = 137620; - -DELETE FROM `creature_template_addon` WHERE `entry` IN (34047, 34148, 33836, 34149, 34147, 33670, 34363, 34121); -INSERT INTO `creature_template_addon` (`entry`, `bytes1`, `bytes2`, `auras`) VALUES -(33670, 50331648, 1, ''), -(34363, 0, 1, '64561'), -(34121, 0, 1, '64561'), -(34047, 0, 1, '64064'), -(34148, 0, 1, '64616 64617'), -(33836, 0, 1, '63767'), -(34149, 0, 1, '64624'), -(34147, 0, 1, '64617'); - -DELETE FROM `creature_text` WHERE `entry` = 34143; -INSERT INTO `creature_text` (`entry`, `groupid`, `text`, `type`, `probability`, `sound`, `BroadcastTextID`) VALUES -(34143, 0, 'Self-destruct sequence initiated.', 14, 100, 15413, 34268), -(34143, 1, 'Self-destruct sequence terminated. Override code A905..', 14, 100, 15414, 34284), -(34143, 2, 'This area will self-destruct in ten minutes.', 14, 100, 15415, 34283), -(34143, 3, 'This area will self-destruct in nine minutes.', 14, 100, 15416, 34282), -(34143, 4, 'This area will self-destruct in eight minutes.', 14, 100, 15417, 34281), -(34143, 5, 'This area will self-destruct in seven minutes.', 14, 100, 15418, 34280), -(34143, 6, 'This area will self-destruct in six minutes.', 14, 100, 15419, 34273), -(34143, 7, 'This area will self-destruct in five minutes.', 14, 100, 15420, 34274), -(34143, 8, 'This area will self-destruct in four minutes.', 14, 100, 15421, 34275), -(34143, 9, 'This area will self-destruct in three minutes.', 14, 100, 15422, 34276), -(34143, 10, 'This area will self-destruct in two minutes.', 14, 100, 15423, 34277), -(34143, 11, 'This area will self-destruct in one minute.', 14, 100, 15424, 34278), -(34143, 12, 'Self-destruct sequence finalized. Have a nice day.', 14, 100, 15425, 34279); - -DELETE FROM `waypoint_data` WHERE `id` = 1376200; -INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_flag`, `action`, `action_chance`, `wpguid`) VALUES -(1376200, 0, 2785.423, 2673.119, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 1, 2823.024, 2649.059, 371.9791, 0, 0, 1, 0, 100, 0), -(1376200, 2, 2854.097, 2590.826, 371.9791, 0, 0, 1, 0, 100, 0), -(1376200, 3, 2852.951, 2547.112, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 4, 2822.796, 2489.515, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 5, 2784.964, 2465.247, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 6, 2741.24, 2456.771, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 7, 2701.036, 2464.319, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 8, 2660.476, 2489.578, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 9, 2636.893, 2525.687, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 10, 2631.294, 2547.831, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 11, 2631.437, 2591.752, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 12, 2637.362, 2613.7, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 13, 2650.221, 2636.163, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 14, 2661.572, 2649.715, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 15, 2696.595, 2672.664, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 16, 2711.099, 2677.791, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 17, 2740.676, 2683.12, 372.3605, 0, 0, 1, 0, 100, 0), -(1376200, 18, 2771.834, 2677.767, 372.3605, 0, 0, 1, 0, 100, 0); - -DELETE FROM `disables` WHERE `sourceType` = 4 AND `entry` IN (10544, 10547, 10543, 10546, 10548, 10545, 10450, 10463, 10406, 10405); - -DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10406, 10405) AND `type` = 18; -DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10545,10548,10546,10543,10547,10544, 10450, 10463) AND `type` = 11; -INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES -(10544, 11, 0, 0, 'achievement_setup_rocket'), -(10547, 11, 0, 0, 'achievement_setup_rocket'), -(10543, 11, 0, 0, 'achievement_setup_mine'), -(10546, 11, 0, 0, 'achievement_setup_mine'), -(10548, 11, 0, 0, 'achievement_setup_boom'), -(10545, 11, 0, 0, 'achievement_setup_boom'), -(10450, 11, 0, 0, 'achievement_firefighter'), -(10463, 11, 0, 0, 'achievement_firefighter'); --- diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index e954b9173ad..6f56c0ebc40 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3347,16 +3347,6 @@ void SpellMgr::LoadSpellInfoCorrections() // that will be clear if we get more spells with problem like this spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY; break; - case 63414: // Spinning Up (Mimiron) - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - spellInfo->ChannelInterruptFlags = 0; - break; - case 63036: // Rocket Strike (Mimiron) - spellInfo->Speed = 0; - break; - case 64668: // Magnetic Field (Mimiron) - spellInfo->Mechanic = MECHANIC_NONE; - break; case 64468: // Empowering Shadows (Yogg-Saron) case 64486: // Empowering Shadows (Yogg-Saron) spellInfo->MaxAffectedTargets = 3; // same for both modes? diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index a3c3077fd71..f284aacf996 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -15,16 +15,10 @@ * with this program. If not, see . */ -#include "Cell.h" -#include "CellImpl.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellScript.h" -#include "SpellAuraEffects.h" #include "ulduar.h" -#include "Vehicle.h" enum Yells { @@ -45,2927 +39,78 @@ enum Yells SAY_BERSERK = 14 }; -enum ComputerYells -{ - SAY_SELF_DESTRUCT_INITIATED = 0, - SAY_SELF_DESTRUCT_TERMINATED = 1, - SAY_SELF_DESTRUCT_10 = 2, - SAY_SELF_DESTRUCT_9 = 3, - SAY_SELF_DESTRUCT_8 = 4, - SAY_SELF_DESTRUCT_7 = 5, - SAY_SELF_DESTRUCT_6 = 6, - SAY_SELF_DESTRUCT_5 = 7, - SAY_SELF_DESTRUCT_4 = 8, - SAY_SELF_DESTRUCT_3 = 9, - SAY_SELF_DESTRUCT_2 = 10, - SAY_SELF_DESTRUCT_1 = 11, - SAY_SELF_DESTRUCT_FINALIZED = 12 -}; - enum Spells { - // Mimiron - SPELL_WELD = 63339, // Idle aura. - SPELL_SEAT_1 = 52391, // Cast on all vehicles, Cycled on MKII - SPELL_SEAT_2 = 63313, // Cast on MKII and VX-001, Cycled on MKII - SPELL_SEAT_3 = 63314, // Cast on MKII, Cycled on MKII - SPELL_SEAT_5 = 63316, // Cast on MKII and VX-001, Cycled on MKII - SPELL_SEAT_6 = 63344, // Cast on MKII - SPELL_SEAT_7 = 63345, // Cast on MKII SPELL_JETPACK = 63341, - SPELL_DESPAWN_ASSAULT_BOTS = 64463, // only despawns assault bots... no equivalent spell for the other adds... - SPELL_TELEPORT_VISUAL = 41232, - SPELL_SLEEP_VISUAL_1 = 64393, - SPELL_SLEEP_VISUAL_2 = 64394, - + SPELL_EMERGENCY_MODE = 64582, + SPELL_SELF_REPAIR = 64383, + SPELL_MAGNETIC_CORE = 64444, // Leviathan MK II SPELL_FLAME_SUPPRESSANT_MK = 64570, SPELL_NAPALM_SHELL = 63666, - SPELL_FORCE_CAST_NAPALM_SHELL = 64539, - SPELL_PLASMA_BLAST = 62997, - SPELL_SCRIPT_EFFECT_PLASMA_BLAST = 64542, + SPELL_PLASMA_BLAST = 62977, + SPELL_PROXIMITY_MINES = 63027, SPELL_SHOCK_BLAST = 63631, - SPELL_SHOCK_BLAST_AURA = 63632, // Deprecated? It is never cast. - - // VX-001 + // VX 001 SPELL_FLAME_SUPPRESSANT_VX = 65192, + SPELL_FROSTBOMB = 64623, + SPELL_HAND_PULSE = 64348, SPELL_SPINNING_UP = 63414, - SPELL_HEAT_WAVE_AURA = 63679, - SPELL_HAND_PULSE_LEFT = 64348, - SPELL_HAND_PULSE_RIGHT = 64352, - SPELL_MOUNT_MKII = 64387, - SPELL_TORSO_DISABLED = 64120, - + SPELL_RAPID_BURST = 63387, + SPELL_P3WX2_LASER_BARRAGE = 63293, + SPELL_ROCKET_STRIKE = 63041, + SPELL_HEAT_WAVE = 63677, // Aerial Command Unit - SPELL_PLASMA_BALL_P1 = 63689, - SPELL_PLASMA_BALL_P2 = 65647, - SPELL_MOUNT_VX_001 = 64388, - - // Proximity Mines - SPELL_PROXIMITY_MINES = 63027, // Cast by Leviathan MK II - SPELL_PROXIMITY_MINE_EXPLOSION = 66351, - SPELL_PROXIMITY_MINE_TRIGGER = 65346, - SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER = 65345, - SPELL_PERIODIC_PROXIMITY_AURA = 65345, - SPELL_SUMMON_PROXIMITY_MINE = 65347, - - // Rapid Burst - SPELL_RAPID_BURST_LEFT = 63387, - SPELL_RAPID_BURST_RIGHT = 64019, - SPELL_RAPID_BURST = 63382, // Cast by VX-001 - SPELL_RAPID_BURST_TARGET_ME = 64841, // Cast by Burst Target - SPELL_SUMMON_BURST_TARGET = 64840, // Cast by VX-001 - - // Rocket Strike - SPELL_SUMMON_ROCKET_STRIKE = 63036, - SPELL_SCRIPT_EFFECT_ROCKET_STRIKE = 63681, // Cast by Rocket (Mimiron Visual) - SPELL_ROCKET_STRIKE = 64064, // Added in creature_template_addon - SPELL_ROCKET_STRIKE_LEFT = 64402, // Cast by VX-001 - SPELL_ROCKET_STRIKE_BOTH = 65034, // Cast by VX-001 - - // Flames - SPELL_FLAMES_PERIODIC_TRIGGER = 64561, // Added in creature_template_addon - SPELL_SUMMON_FLAMES_SPREAD_TRIGGER = 64562, - SPELL_SUMMON_FLAMES_INITIAL = 64563, - SPELL_SUMMON_FLAMES_SPREAD = 64564, - SPELL_FLAMES = 64566, - SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL = 64567, - - // Frost Bomb - SPELL_SCRIPT_EFFECT_FROST_BOMB = 64623, // Cast by VX-001 - SPELL_FROST_BOMB_LINKED = 64624, // Added in creature_template_addon - SPELL_FROST_BOMB_DUMMY = 64625, - SPELL_SUMMON_FROST_BOMB = 64627, // Cast by VX-001 - SPELL_FROST_BOMB_EXPLOSION = 64626, - SPELL_CLEAR_FIRES = 65354, - - // Bots - SPELL_SUMMON_FIRE_BOT = 64622, - SPELL_SUMMON_FIRE_BOT_DUMMY = 64621, - SPELL_SUMMON_FIRE_BOT_TRIGGER = 64620, // Cast by Areal Command Unit - SPELL_DEAFENING_SIREN = 64616, // Added in creature_template_addon - SPELL_FIRE_SEARCH_AURA = 64617, // Added in creature_template_addon - SPELL_FIRE_SEARCH = 64618, - SPELL_WATER_SPRAY = 64619, - - SPELL_SUMMON_JUNK_BOT = 63819, - SPELL_SUMMON_JUNK_BOT_TRIGGER = 63820, // Cast by Areal Command Unit - SPELL_SUMMON_JUNK_BOT_DUMMY = 64398, - - SPELL_SUMMON_ASSAULT_BOT_TRIGGER = 64425, // Cast by Areal Command Unit - SPELL_SUMMON_ASSAULT_BOT_DUMMY = 64426, - SPELL_SUMMON_ASSAULT_BOT = 64427, + SPELL_PLASMA_BALL = 63689, + // Additonal spells SPELL_MAGNETIC_FIELD = 64668, - - SPELL_SUMMON_BOMB_BOT = 63811, // Cast by Areal Command Unit - SPELL_BOMB_BOT_AURA = 63767, // Added in creature_template_addon - - // Miscellaneous - SPELL_SELF_DESTRUCTION_AURA = 64610, - SPELL_SELF_DESTRUCTION_VISUAL = 64613, - SPELL_NOT_SO_FRIENDLY_FIRE = 65040, - SPELL_ELEVATOR_KNOCKBACK = 65096, // Cast by worldtrigger. - SPELL_VEHICLE_DAMAGED = 63415, - SPELL_EMERGENCY_MODE = 64582, // mkii, vx001, aerial, assault, junk - SPELL_EMERGENCY_MODE_TURRET = 65101, // Cast by Leviathan MK II, only hits Leviathan MK II turret - SPELL_SELF_REPAIR = 64383, - SPELL_MAGNETIC_CORE = 64436, - SPELL_MAGNETIC_CORE_VISUAL = 64438, - SPELL_HALF_HEAL = 64188, - SPELL_CLEAR_ALL_DEBUFFS = 34098, // TODO: make use of this spell... - SPELL_FREEZE_ANIM_STUN = 63354, // used to prevent mkii from doing stuff?.. - SPELL_FREEZE_ANIM = 16245 // Idle aura. Freezes animation. -}; - -enum Data -{ - DATA_SETUP_MINE, - DATA_SETUP_BOMB, - DATA_SETUP_ROCKET, - DATA_NOT_SO_FRIENDLY_FIRE, - DATA_FIREFIGHTER, - DATA_WATERSPRAY, - DATA_MOVE_NEW -}; - -enum Events -{ - EVENT_NONE, - - // Leviathan MK II - EVENT_PROXIMITY_MINE, - EVENT_NAPALM_SHELL, - EVENT_PLASMA_BLAST, - EVENT_SHOCK_BLAST, - EVENT_FLAME_SUPPRESSANT_MK, - - // VX-001 - EVENT_RAPID_BURST, - EVENT_SPINNING_UP, - EVENT_ROCKET_STRIKE, - EVENT_HAND_PULSE, - EVENT_FROST_BOMB, - EVENT_FLAME_SUPPRESSANT_VX, - EVENT_RELOAD, - - // Aerial Command Unit - EVENT_SUMMON_FIRE_BOTS, - EVENT_SUMMON_JUNK_BOT, - EVENT_SUMMON_ASSAULT_BOT, - EVENT_SUMMON_BOMB_BOT, - - // Mimiron - EVENT_SUMMON_FLAMES, - EVENT_INTRO_1, - EVENT_INTRO_2, - EVENT_INTRO_3, - - EVENT_VX001_ACTIVATION_1, - EVENT_VX001_ACTIVATION_2, - EVENT_VX001_ACTIVATION_3, - EVENT_VX001_ACTIVATION_4, - EVENT_VX001_ACTIVATION_5, - EVENT_VX001_ACTIVATION_6, - EVENT_VX001_ACTIVATION_7, - EVENT_VX001_ACTIVATION_8, - EVENT_VX001_ACTIVATION_9, - - EVENT_AERIAL_ACTIVATION_1, - EVENT_AERIAL_ACTIVATION_2, - EVENT_AERIAL_ACTIVATION_3, - EVENT_AERIAL_ACTIVATION_4, - EVENT_AERIAL_ACTIVATION_5, - EVENT_AERIAL_ACTIVATION_6, - - EVENT_VOL7RON_ACTIVATION_1, - EVENT_VOL7RON_ACTIVATION_2, - EVENT_VOL7RON_ACTIVATION_3, - EVENT_VOL7RON_ACTIVATION_4, - EVENT_VOL7RON_ACTIVATION_5, - EVENT_VOL7RON_ACTIVATION_6, - EVENT_VOL7RON_ACTIVATION_7, - - EVENT_OUTTRO_1, - EVENT_OUTTRO_2, - EVENT_OUTTRO_3, - - // Computer - EVENT_SELF_DESTRUCT_10, - EVENT_SELF_DESTRUCT_9, - EVENT_SELF_DESTRUCT_8, - EVENT_SELF_DESTRUCT_7, - EVENT_SELF_DESTRUCT_6, - EVENT_SELF_DESTRUCT_5, - EVENT_SELF_DESTRUCT_4, - EVENT_SELF_DESTRUCT_3, - EVENT_SELF_DESTRUCT_2, - EVENT_SELF_DESTRUCT_1, - EVENT_SELF_DESTRUCT_FINALIZED -}; - -enum Actions -{ - DO_START_MKII, - DO_HARDMODE_MKII, - - DO_ACTIVATE_VX001, - DO_START_VX001, - DO_HARDMODE_VX001, - - DO_ACTIVATE_AERIAL, - DO_START_AERIAL, - DO_HARDMODE_AERIAL, - DO_DISABLE_AERIAL, - DO_ENABLE_AERIAL, - - DO_ACTIVATE_V0L7R0N_1, - DO_ACTIVATE_V0L7R0N_2, - DO_ASSEMBLED_COMBAT, // All 3 parts use this action, its done on purpose. - - DO_ACTIVATE_HARD_MODE, - DO_ACTIVATE_COMPUTER, - DO_DEACTIVATE_COMPUTER, - DO_ACTIVATE_SELF_DESTRUCT, - - DO_ENCOUNTER_DONE -}; - -enum Waypoints -{ - WP_NONE, - WP_MKII_P1_IDLE, - WP_MKII_P4_POS_1, - WP_MKII_P4_POS_2, - WP_MKII_P4_POS_3, - WP_MKII_P4_POS_4, - WP_MKII_P4_POS_5, - WP_AERIAL_P4_POS -}; - -enum Phases -{ - PHASE_NULL, - - // Leviathan MK II - PHASE_LEVIATHAN_SOLO, - PHASE_LEVIATHAN_ASSEMBLED, - - // VX-001 - PHASE_VX001_SOLO, - PHASE_VX001_ASSEMBLED, - - // Aerial Command Unit - PHASE_AERIAL_SOLO, - PHASE_AERIAL_ASSEMBLED -}; - -uint32 const repairSpells[4] = -{ - SPELL_SEAT_1, - SPELL_SEAT_2, - SPELL_SEAT_3, - SPELL_SEAT_5 -}; - -Position const pos[] = -{ - {}, - { 2792.070f, 2596.320f, 364.3136f }, // WP_MKII_P1_IDLE - { 2765.945f, 2571.095f, 364.0636f }, // WP_MKII_P4_POS_1 - { 2768.195f, 2573.095f, 364.0636f }, // WP_MKII_P4_POS_2 - { 2763.820f, 2568.870f, 364.3136f }, // WP_MKII_P4_POS_3 - { 2761.215f, 2568.875f, 364.0636f }, // WP_MKII_P4_POS_4 - { 2744.610f, 2569.380f, 364.3136f }, // WP_MKII_P4_POS_5 - { 2748.513f, 2569.051f, 364.3136f } // WP_AERIAL_P4_POS -}; - -class AerialTargetSelector -{ - public: - AerialTargetSelector() {} - - bool operator() (WorldObject* target) const - { - if (Unit* unit = target->ToUnit()) - { - if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return true; - - if (unit->GetVehicleBase()) - return true; - } - return false; - } -}; - -class EncounterDone -{ - Unit* _who; - Creature* _vehiclePart; - public: - EncounterDone(Unit* who, Creature* vehiclePart) : _who(who), _vehiclePart(vehiclePart) {} - - bool IsEncounterFinished() - { - if (InstanceScript* instance = _vehiclePart->GetInstanceScript()) - if (Creature* mkii = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(DATA_LEVIATHAN_MK_II))) - if (Creature* vx001 = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(DATA_VX_001))) - if (Creature* aerial = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(DATA_AERIAL_COMMAND_UNIT))) - if (mkii->getStandState() == UNIT_STAND_STATE_DEAD && vx001->getStandState() == UNIT_STAND_STATE_DEAD && aerial->getStandState() == UNIT_STAND_STATE_DEAD) - { - _who->Kill(mkii); - _who->Kill(vx001); - _who->Kill(aerial); - mkii->DespawnOrUnsummon(120000); - vx001->DespawnOrUnsummon(120000); - aerial->DespawnOrUnsummon(120000); - if (Creature* mimiron = ObjectAccessor::GetCreature(*_vehiclePart, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->JustDied(_who); - return true; - } - return false; - } -}; - -class boss_mimiron : public CreatureScript -{ - public: - boss_mimiron() : CreatureScript("boss_mimiron") { } - - struct boss_mimironAI : public BossAI - { - boss_mimironAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) - { - me->SetReactState(REACT_PASSIVE); - me->SetDisableGravity(true); - } - - void DoAction(int32 action) override - { - switch (action) - { - case DO_ACTIVATE_VX001: - events.ScheduleEvent(EVENT_VX001_ACTIVATION_1, 1000); - break; - case DO_ACTIVATE_AERIAL: - events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_1, 5000); - break; - case DO_ACTIVATE_V0L7R0N_1: - Talk(SAY_AERIAL_DEATH); - if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) - mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_3, pos[WP_MKII_P4_POS_3]); // MovePoint(WP_MKII_P4_POS_1, pos[WP_MKII_P4_POS_1]); - break; - case DO_ACTIVATE_V0L7R0N_2: - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_1, 1000); - break; - case DO_ACTIVATE_HARD_MODE: - _fireFighter = true; - DoZoneInCombat(me); - break; - default: - break; - } - } - - void EnterCombat(Unit* /*who*/) override - { - if (!me->GetVehicleBase()) - return; - - _EnterCombat(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_WELD); - DoCast(me->GetVehicleBase(), SPELL_SEAT_6); - - if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON))) - button->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - - if (_fireFighter) - events.ScheduleEvent(EVENT_SUMMON_FLAMES, 3000); - events.ScheduleEvent(EVENT_INTRO_1, 1500); - } - - void JustDied(Unit* /*who*/) override - { - instance->SetBossState(BOSS_MIMIRON, DONE); - events.Reset(); - me->CombatStop(true); - me->SetDisableGravity(false); - DoCast(me, SPELL_SLEEP_VISUAL_1); - DoCastAOE(SPELL_DESPAWN_ASSAULT_BOTS); - me->ExitVehicle(); - // ExitVehicle() offset position is not implemented, so we make up for that with MoveJump()... - me->GetMotionMaster()->MoveJump(me->GetPositionX() + (float)(10 * cos(me->GetOrientation())), me->GetPositionY() + (float)(10 * sin(me->GetOrientation())), me->GetPositionZ(), 10.0f, 5.0f); - events.ScheduleEvent(EVENT_OUTTRO_1, 7000); - } - - void Reset() override - { - if (instance->GetBossState(BOSS_MIMIRON) == DONE) // Mimiron will attempt to reset because he is not dead and will be set to friendly before despawning. - return; - - _Reset(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_ACTIVE); - - if (_fireFighter) - if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER))) - computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); - - if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON))) - { - button->SetGoState(GO_STATE_READY); - button->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_NOT_SELECTABLE); - } - - _fireFighter = false; - DoCast(me, SPELL_WELD); - - if (Unit* mkii = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) - DoCast(mkii, SPELL_SEAT_3); - } - - void UpdateAI(uint32 diff) override - { - if ((!UpdateVictim() || !CheckInRoom()) && instance->GetBossState(BOSS_MIMIRON) != DONE) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SUMMON_FLAMES: - if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER))) - worldtrigger->CastSpell((Unit*)NULL, SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL, true, NULL, NULL, me->GetGUID()); - events.RescheduleEvent(EVENT_SUMMON_FLAMES, 28000); - break; - case EVENT_INTRO_1: - Talk(_fireFighter ? SAY_HARDMODE_ON : SAY_MKII_ACTIVATE); - events.ScheduleEvent(EVENT_INTRO_2, 5000); - break; - case EVENT_INTRO_2: - if (Unit* mkii = me->GetVehicleBase()) - { - DoCast(mkii, SPELL_SEAT_7); - mkii->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - mkii->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - } - events.ScheduleEvent(EVENT_INTRO_3, 2000); - break; - case EVENT_INTRO_3: - me->GetVehicleBase()->GetAI()->DoAction(_fireFighter? DO_HARDMODE_MKII : DO_START_MKII); - break; - case EVENT_VX001_ACTIVATION_1: - me->GetVehicleBase()->SetFacingTo(3.686f); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_2, 1000); - break; - case EVENT_VX001_ACTIVATION_2: - DoCast(me->GetVehicleBase(), SPELL_SEAT_6); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_3, 1000); - break; - case EVENT_VX001_ACTIVATION_3: - Talk(SAY_MKII_DEATH); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_4, 5000); - break; - case EVENT_VX001_ACTIVATION_4: - instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_READY); - if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER))) - worldtrigger->CastSpell(worldtrigger, SPELL_ELEVATOR_KNOCKBACK); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_5, 6000); - break; - case EVENT_VX001_ACTIVATION_5: - me->SummonCreature(NPC_VX_001, 2744.431f, 2569.385f, 364.3968f, 3.141593f, TEMPSUMMON_MANUAL_DESPAWN); - instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_ACTIVE_ALTERNATIVE); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_6, 19000); - break; - case EVENT_VX001_ACTIVATION_6: - if (Unit* vx001 = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_VX_001))) - DoCast(vx001, SPELL_SEAT_1); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_7, 3500); - break; - case EVENT_VX001_ACTIVATION_7: - Talk(SAY_VX001_ACTIVATE); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_8, 4000); - break; - case EVENT_VX001_ACTIVATION_8: - DoCast(me->GetVehicleBase(), SPELL_SEAT_2); - events.ScheduleEvent(EVENT_VX001_ACTIVATION_9, 3000); - break; - case EVENT_VX001_ACTIVATION_9: - me->GetVehicleBase()->GetAI()->DoAction(_fireFighter ? DO_HARDMODE_VX001 : DO_START_VX001); - break; - case EVENT_AERIAL_ACTIVATION_1: - DoCast(me->GetVehicleBase(), SPELL_SEAT_5); - events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_2, 2500); - break; - case EVENT_AERIAL_ACTIVATION_2: - Talk(SAY_VX001_DEATH); - events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_3, 5000); - break; - case EVENT_AERIAL_ACTIVATION_3: - me->SummonCreature(NPC_AERIAL_COMMAND_UNIT, 2744.65f, 2569.46f, 380, 0, TEMPSUMMON_MANUAL_DESPAWN); - events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_4, 5000); - break; - case EVENT_AERIAL_ACTIVATION_4: - if (Unit* aerial = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT))) - me->CastSpell(aerial, SPELL_SEAT_1); - events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_5, 2000); - break; - case EVENT_AERIAL_ACTIVATION_5: - Talk(SAY_AERIAL_ACTIVATE); - events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_6, 8000); - break; - case EVENT_AERIAL_ACTIVATION_6: - me->GetVehicleBase()->GetAI()->DoAction(_fireFighter? DO_HARDMODE_AERIAL : DO_START_AERIAL); - break; - case EVENT_VOL7RON_ACTIVATION_1: - if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) - mkii->SetFacingTo(M_PI); - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_2, 1000); - break; - case EVENT_VOL7RON_ACTIVATION_2: - if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) - if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001))) - { - vx001->RemoveAurasDueToSpell(SPELL_TORSO_DISABLED); - vx001->CastSpell(mkii, SPELL_MOUNT_MKII); - } - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_3, 4500); - break; - case EVENT_VOL7RON_ACTIVATION_3: - if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II))) - mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_5, pos[WP_MKII_P4_POS_5]); // MovePoint(WP_MKII_P4_POS_4, pos[WP_MKII_P4_POS_4]); - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_4, 5000); - break; - case EVENT_VOL7RON_ACTIVATION_4: - if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001))) - if (Creature* aerial = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT))) - { - aerial->GetMotionMaster()->MoveLand(0, (aerial->GetPositionX(), aerial->GetPositionY(), aerial->GetPositionZMinusOffset())); - //aerial->SetDisableGravity(false); - //aerial->SetHover(false); - aerial->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - aerial->CastSpell(vx001, SPELL_MOUNT_VX_001); - aerial->CastSpell(aerial, SPELL_HALF_HEAL); - } - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_5, 4000); - break; - case EVENT_VOL7RON_ACTIVATION_5: - Talk(SAY_V07TRON_ACTIVATE); - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_6, 3000); - break; - case EVENT_VOL7RON_ACTIVATION_6: - if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001))) - DoCast(vx001, SPELL_SEAT_2); - events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_7, 5000); - break; - case EVENT_VOL7RON_ACTIVATION_7: - for (uint8 data = DATA_LEVIATHAN_MK_II; data <= DATA_AERIAL_COMMAND_UNIT; data++) - if (Creature* mimironVehicle = ObjectAccessor::GetCreature(*me, instance->GetData64(data))) - mimironVehicle->AI()->DoAction(DO_ASSEMBLED_COMBAT); - break; - case EVENT_OUTTRO_1: - me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1); - DoCast(me, SPELL_SLEEP_VISUAL_2); - me->setFaction(35); - events.ScheduleEvent(EVENT_OUTTRO_2, 3000); - break; - case EVENT_OUTTRO_2: - Talk(SAY_V07TRON_DEATH); - if (_fireFighter) - { - if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER))) - computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); - me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.65f, 2569.46f, 364.314f, 3.14159f, 0, 0, 0.7f, 0.7f, 604800); - } - else - me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION, GO_CACHE_OF_INNOVATION_HERO), 2744.65f, 2569.46f, 364.314f, 3.14159f, 0, 0, 0.7f, 0.7f, 604800); - events.ScheduleEvent(EVENT_OUTTRO_3, 11000); - break; - case EVENT_OUTTRO_3: - DoCast(me, SPELL_TELEPORT_VISUAL); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->DespawnOrUnsummon(1000); // sniffs say 6 sec after, but it doesnt matter. - break; - default: - break; - } - } - } - - private: - bool _fireFighter; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class boss_leviathan_mk_ii : public CreatureScript -{ - public: - boss_leviathan_mk_ii() : CreatureScript("boss_leviathan_mk_ii") { } - - struct boss_leviathan_mk_iiAI : public BossAI - { - boss_leviathan_mk_iiAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) - { - } - - void DamageTaken(Unit* who, uint32 &damage) override - { - if (damage >= me->GetHealth()) - { - damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth(). - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_VEHICLE_DAMAGED, true); - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); - - if (events.IsInPhase(PHASE_LEVIATHAN_SOLO)) - { - me->CastStop(); - if (Unit* turret = me->GetVehicleKit()->GetPassenger(3)) - turret->Kill(turret); - - me->SetSpeed(MOVE_RUN, 1.5f, true); - me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, pos[WP_MKII_P1_IDLE]); - } - else if (events.IsInPhase(PHASE_LEVIATHAN_ASSEMBLED)) - { - me->SetStandState(UNIT_STAND_STATE_DEAD); - - if (EncounterDone(who, me).IsEncounterFinished()) - return; - - me->CastStop(); - DoCast(me, SPELL_SELF_REPAIR); - } - events.Reset(); - } - } - - void DoAction(int32 action) override - { - switch (action) - { - case DO_HARDMODE_MKII: - _fireFighter = true; - DoCast(me, SPELL_EMERGENCY_MODE); - DoCastAOE(SPELL_EMERGENCY_MODE_TURRET); - events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_SOLO); - // Missing break intended. - case DO_START_MKII: - _setupMine = true; - _setupBomb = true; - _setupRocket = true; - - me->SetReactState(REACT_AGGRESSIVE); - events.SetPhase(PHASE_LEVIATHAN_SOLO); - - events.ScheduleEvent(EVENT_NAPALM_SHELL, 3000, 0, PHASE_LEVIATHAN_SOLO); - events.ScheduleEvent(EVENT_PLASMA_BLAST, 15000, 0, PHASE_LEVIATHAN_SOLO); - events.ScheduleEvent(EVENT_PROXIMITY_MINE, 5000); - events.ScheduleEvent(EVENT_SHOCK_BLAST, 18000); - break; - case DO_ASSEMBLED_COMBAT: - me->SetStandState(UNIT_STAND_STATE_STAND); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - - events.SetPhase(PHASE_LEVIATHAN_ASSEMBLED); - events.ScheduleEvent(EVENT_PROXIMITY_MINE, 15000); - events.ScheduleEvent(EVENT_SHOCK_BLAST, 45000); - break; - default: - break; - } - } - - uint32 GetData(uint32 type) const override - { - switch (type) - { - case DATA_SETUP_MINE: - return _setupMine; - case DATA_SETUP_BOMB: - return _setupBomb; - case DATA_SETUP_ROCKET: - return _setupRocket; - case DATA_FIREFIGHTER: - return _fireFighter; - default: - return 0; - } - } - - void JustDied(Unit* /*who*/) override - { - _JustDied(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - if (mimiron->AI()) - mimiron->AI()->Talk(events.IsInPhase(PHASE_LEVIATHAN_SOLO) ? SAY_MKII_SLAY : SAY_V07TRON_SLAY); - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != POINT_MOTION_TYPE) - return; - - switch (point) - { - case WP_MKII_P1_IDLE: - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_HALF_HEAL); - - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->DoAction(DO_ACTIVATE_VX001); - break; - case WP_MKII_P4_POS_1: - me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_2, pos[WP_MKII_P4_POS_2]); - break; - case WP_MKII_P4_POS_2: - me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_3, pos[WP_MKII_P4_POS_3]); - break; - case WP_MKII_P4_POS_3: - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_2); - break; - case WP_MKII_P4_POS_4: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_5, pos[WP_MKII_P4_POS_5]); - break; - default: - break; - } - } - - void Reset() override - { - _Reset(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); - _fireFighter = false; - _setupMine = false; - _setupBomb = false; - _setupRocket = false; - DoCast(me, SPELL_FREEZE_ANIM); - } - - void SetData(uint32 id, uint32 data) override - { - switch (id) - { - case DATA_SETUP_MINE: - _setupMine = data; - break; - case DATA_SETUP_BOMB: - _setupBomb = data; - break; - case DATA_SETUP_ROCKET: - _setupRocket = data; - break; - case DATA_FIREFIGHTER: - _fireFighter = data; - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() || !CheckInRoom()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_PROXIMITY_MINE: - DoCastAOE(SPELL_PROXIMITY_MINES); - events.RescheduleEvent(EVENT_PROXIMITY_MINE, 35000); - break; - case EVENT_PLASMA_BLAST: - DoCastVictim(SPELL_SCRIPT_EFFECT_PLASMA_BLAST); - events.RescheduleEvent(EVENT_PLASMA_BLAST, urand(30000, 45000), 0, PHASE_LEVIATHAN_SOLO); - - if (events.GetTimeUntilEvent(EVENT_NAPALM_SHELL) < 9000) - events.RescheduleEvent(EVENT_NAPALM_SHELL, 9000, 0, PHASE_LEVIATHAN_SOLO); // The actual spell is cast by the turret, we should not let it interrupt itself. - break; - case EVENT_SHOCK_BLAST: - DoCastAOE(SPELL_SHOCK_BLAST); - events.RescheduleEvent(EVENT_SHOCK_BLAST, urand(34000, 36000)); - break; - case EVENT_FLAME_SUPPRESSANT_MK: - DoCastAOE(SPELL_FLAME_SUPPRESSANT_MK); - events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_SOLO); - break; - case EVENT_NAPALM_SHELL: - DoCastAOE(SPELL_FORCE_CAST_NAPALM_SHELL); - events.RescheduleEvent(EVENT_NAPALM_SHELL, urand(6000, 15000), 0, PHASE_LEVIATHAN_SOLO); - - if (events.GetTimeUntilEvent(EVENT_PLASMA_BLAST) < 2000) - events.RescheduleEvent(EVENT_PLASMA_BLAST, 2000, 0, PHASE_LEVIATHAN_SOLO); // The actual spell is cast by the turret, we should not let it interrupt itself. - break; - default: - break; - } - } - DoMeleeAttackIfReady(); - } - - private: - bool _fireFighter; - bool _setupMine; - bool _setupBomb; - bool _setupRocket; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } + SPELL_DEAFENING_SIREN = 64616, + SPELL_WATER_SPRAY = 64619, + SPELL_FROST_BOMB_HARD_MODE = 64627, + SPELL_EXPLOSION = 66351, + SPELL_DISARM = 1842, + SPELL_RIDE_VEHICLE = 46598, + SPELL_TRIGGER_MISSILE = 65347, }; -class boss_vx_001 : public CreatureScript +enum Npc { - public: - boss_vx_001() : CreatureScript("boss_vx_001") { } - - struct boss_vx_001AI : public BossAI - { - boss_vx_001AI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) - { - me->SetDisableGravity(true); // This is the unfold visual state of VX-001, it has to be set on create as it requires an objectupdate if set later. - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SPECIAL_UNARMED); // This is a hack to force the yet to be unfolded visual state. - me->SetReactState(REACT_PASSIVE); - DoCast(me, SPELL_FREEZE_ANIM); - _fireFighter = false; - } - - void DamageTaken(Unit* who, uint32 &damage) override - { - if (damage >= me->GetHealth()) - { - damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth(). - me->AttackStop(); - me->SetUInt64Value(UNIT_FIELD_TARGET, NULL); // This should be removed when channel track target implementation is properly functioning. - DoCast(me, SPELL_VEHICLE_DAMAGED, true); - me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); - - if (events.IsInPhase(PHASE_VX001_SOLO)) - { - me->CastStop(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_HALF_HEAL); - DoCast(me, SPELL_TORSO_DISABLED); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->DoAction(DO_ACTIVATE_AERIAL); - } - else if (events.IsInPhase(PHASE_VX001_ASSEMBLED)) - { - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (EncounterDone(who, me).IsEncounterFinished()) - return; - - me->CastStop(); - DoCast(me, SPELL_SELF_REPAIR); - } - events.Reset(); - } - } - - void DoAction(int32 action) override - { - switch (action) - { - case DO_HARDMODE_VX001: - _fireFighter = true; - DoCast(me, SPELL_EMERGENCY_MODE); - events.ScheduleEvent(EVENT_FROST_BOMB, 1000); - events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, 6000); - // Missing break intended. - case DO_START_VX001: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); // Remove emotestate. - //me->SetUInt32Value(UNIT_FIELD_BYTES_1, 33554432); Blizzard handles hover animation like this it seems. - DoCast(me, SPELL_HEAT_WAVE_AURA); - - events.SetPhase(PHASE_VX001_SOLO); - events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000); - events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000)); - events.ScheduleEvent(EVENT_RAPID_BURST, 500, 0, PHASE_VX001_SOLO); - break; - case DO_ASSEMBLED_COMBAT: - me->SetStandState(UNIT_STAND_STATE_STAND); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - - events.SetPhase(PHASE_VX001_ASSEMBLED); - events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000); - events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000)); - events.ScheduleEvent(EVENT_HAND_PULSE, 500, 0, PHASE_VX001_ASSEMBLED); - if (_fireFighter) - events.ScheduleEvent(EVENT_FROST_BOMB, 1000); - break; - default: - break; - } - } - - void EnterEvadeMode() override - { - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - if (summon->GetEntry() == NPC_BURST_TARGET) - summon->CastSpell(me, SPELL_RAPID_BURST_TARGET_ME); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - if (mimiron->AI()) - mimiron->AI()->Talk(events.IsInPhase(PHASE_VX001_SOLO) ? SAY_VX001_SLAY : SAY_V07TRON_SLAY); - } - - void SpellHit(Unit* caster, SpellInfo const* /*spellProto*/) override - { - if (caster->GetEntry() == NPC_BURST_TARGET && !me->HasUnitState(UNIT_STATE_CASTING)) - DoCast(caster, SPELL_RAPID_BURST); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - // Handle rotation during SPELL_SPINNING_UP, SPELL_P3WX2_LASER_BARRAGE, SPELL_RAPID_BURST, and SPELL_HAND_PULSE_LEFT/RIGHT - if (me->HasUnitState(UNIT_STATE_CASTING)) - { - if (Creature* channelTarget = ObjectAccessor::GetCreature(*me, me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT))) - me->SetFacingToObject(channelTarget); - return; - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_RAPID_BURST: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true)) - DoCast(target, SPELL_SUMMON_BURST_TARGET); - events.RescheduleEvent(EVENT_RAPID_BURST, 3000, 0, PHASE_VX001_SOLO); - break; - case EVENT_ROCKET_STRIKE: - DoCastAOE(events.IsInPhase(PHASE_VX001_SOLO) ? SPELL_ROCKET_STRIKE_LEFT : SPELL_ROCKET_STRIKE_BOTH); - events.ScheduleEvent(EVENT_RELOAD, 10000); - events.RescheduleEvent(EVENT_ROCKET_STRIKE, urand(20000, 25000)); - break; - case EVENT_RELOAD: - for (uint8 seat = 6; seat <= 7; seat++) - if (Unit* rocket = me->GetVehicleKit()->GetPassenger(seat)) - rocket->SetDisplayId(rocket->GetNativeDisplayId()); - break; - case EVENT_HAND_PULSE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true)) - DoCast(target, urand(0,1) == 0 ? SPELL_HAND_PULSE_LEFT : SPELL_HAND_PULSE_RIGHT); - events.RescheduleEvent(EVENT_HAND_PULSE, urand(1500, 3000), 0, PHASE_VX001_ASSEMBLED); - break; - case EVENT_FROST_BOMB: - DoCastAOE(SPELL_SCRIPT_EFFECT_FROST_BOMB); - events.RescheduleEvent(EVENT_FROST_BOMB, 45000); - break; - case EVENT_SPINNING_UP: - DoCastAOE(SPELL_SPINNING_UP); - events.DelayEvents(14000); - events.RescheduleEvent(EVENT_SPINNING_UP, urand(55000, 65000)); - break; - case EVENT_FLAME_SUPPRESSANT_VX: - DoCastAOE(SPELL_FLAME_SUPPRESSANT_VX); - events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, urand(10000, 12000), 0, PHASE_VX001_SOLO); - break; - default: - break; - } - } - } - - private: - bool _fireFighter; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } + NPC_ASSAULT_BOT = 34057, + NPC_BOMB_BOT = 33836, + NPC_JUNK_BOT = 33855, + NPC_EMERGENCE_FIRE_BOT = 34147, + NPC_FROST_BOMB = 34149, }; -class boss_aerial_command_unit : public CreatureScript +class spell_ulduar_proximity_mines : public SpellScriptLoader { public: - boss_aerial_command_unit() : CreatureScript("boss_aerial_command_unit") { } + spell_ulduar_proximity_mines() : SpellScriptLoader("spell_ulduar_proximity_mines") { } - struct boss_aerial_command_unitAI : public BossAI + class spell_ulduar_proximity_minesSpellScript : public SpellScript { - boss_aerial_command_unitAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON) - { - //me->SetDisableGravity(true); - me->SetReactState(REACT_PASSIVE); - fireFigther = false; - } - - void DamageTaken(Unit* who, uint32 &damage) override - { - if (damage >= me->GetHealth()) - { - damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth(). - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - DoCast(me, SPELL_VEHICLE_DAMAGED, true); - me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT); - - if (events.IsInPhase(PHASE_AERIAL_SOLO)) - { - me->GetMotionMaster()->Clear(true); - me->GetMotionMaster()->MovePoint(WP_AERIAL_P4_POS, pos[WP_AERIAL_P4_POS]); - } - else if (events.IsInPhase(PHASE_AERIAL_ASSEMBLED)) - { - me->SetStandState(UNIT_STAND_STATE_DEAD); - - if (EncounterDone(who, me).IsEncounterFinished()) - return; - - me->CastStop(); - DoCast(me, SPELL_SELF_REPAIR); - } - events.Reset(); - } - } - - void DoAction(int32 action) override - { - switch (action) - { - case DO_HARDMODE_AERIAL: - fireFigther = true; - DoCast(me, SPELL_EMERGENCY_MODE); - events.ScheduleEvent(EVENT_SUMMON_FIRE_BOTS, 1000, 0, PHASE_AERIAL_SOLO); - // Missing break intended. - case DO_START_AERIAL: - //me->SetDisableGravity(false); - //me->SetHover(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - - events.SetPhase(PHASE_AERIAL_SOLO); - events.ScheduleEvent(EVENT_SUMMON_JUNK_BOT, 5000, 0, PHASE_AERIAL_SOLO); - events.ScheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 9000, 0, PHASE_AERIAL_SOLO); - events.ScheduleEvent(EVENT_SUMMON_BOMB_BOT, 9000, 0, PHASE_AERIAL_SOLO); - break; - case DO_DISABLE_AERIAL: - //me->SetHover(false); - me->CastStop(); - me->AttackStop(); - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveFall(); - events.DelayEvents(23000); - break; - case DO_ENABLE_AERIAL: - //me->SetHover(true); - me->SetReactState(REACT_AGGRESSIVE); - break; - case DO_ASSEMBLED_COMBAT: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - me->SetStandState(UNIT_STAND_STATE_STAND); - events.SetPhase(PHASE_AERIAL_ASSEMBLED); - break; - default: - break; - } - } - - void EnterEvadeMode() override - { - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) override - { - if (fireFigther && (summon->GetEntry() == NPC_ASSAULT_BOT || summon->GetEntry() == NPC_JUNK_BOT)) - summon->AddAura(SPELL_EMERGENCY_MODE, summon); - BossAI::JustSummoned(summon); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - if (mimiron->AI()) - mimiron->AI()->Talk(events.IsInPhase(PHASE_AERIAL_SOLO) ? SAY_AERIAL_SLAY : SAY_V07TRON_SLAY); - } + PrepareSpellScript(spell_ulduar_proximity_minesSpellScript); - void MovementInform(uint32 type, uint32 point) override + void HandleScript(SpellEffIndex effIndex) { - if (type == POINT_MOTION_TYPE && point == WP_AERIAL_P4_POS) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_1); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SUMMON_FIRE_BOTS: - DoCastAOE(SPELL_SUMMON_FIRE_BOT_TRIGGER); - events.RescheduleEvent(EVENT_SUMMON_FIRE_BOTS, 45000, 0, PHASE_AERIAL_SOLO); - break; - case EVENT_SUMMON_JUNK_BOT: - DoCastAOE(SPELL_SUMMON_JUNK_BOT_TRIGGER); - events.RescheduleEvent(EVENT_SUMMON_JUNK_BOT, urand(11000, 12000), 0, PHASE_AERIAL_SOLO); - break; - case EVENT_SUMMON_ASSAULT_BOT: - DoCastAOE(SPELL_SUMMON_ASSAULT_BOT_TRIGGER); - events.RescheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 30000, 0, PHASE_AERIAL_SOLO); - break; - case EVENT_SUMMON_BOMB_BOT: - DoCast(me, SPELL_SUMMON_BOMB_BOT); - events.RescheduleEvent(EVENT_SUMMON_BOMB_BOT, urand(15000, 20000), 0, PHASE_AERIAL_SOLO); - break; - default: - break; - } - } - DoSpellAttackIfReady(events.IsInPhase(PHASE_AERIAL_SOLO) ? SPELL_PLASMA_BALL_P1 : SPELL_PLASMA_BALL_P2); + PreventHitDefaultEffect(effIndex); + for (uint8 i = 0; i < 10; ++i) + GetCaster()->CastSpell(GetCaster(), SPELL_TRIGGER_MISSILE, true); } - private: - bool fireFigther; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class npc_magnetic_core : public CreatureScript -{ - public: - npc_magnetic_core() : CreatureScript("npc_magnetic_core") { } - - struct npc_magnetic_coreAI : public ScriptedAI - { - npc_magnetic_coreAI(Creature* creature) : ScriptedAI(creature) + void Register() override { - DoCast(me, SPELL_MAGNETIC_CORE); - me->DespawnOrUnsummon(25000); // Just incase handling in aurascript fails to despawn. + OnEffectHitTarget += SpellEffectFn(spell_ulduar_proximity_minesSpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; - CreatureAI* GetAI(Creature* creature) const override + SpellScript* GetSpellScript() const override { - return GetUlduarAI(creature); + return new spell_ulduar_proximity_minesSpellScript(); } }; -class npc_mimiron_assault_bot : public CreatureScript +void AddSC_boss_mimiron() { - public: - npc_mimiron_assault_bot() : CreatureScript("npc_mimiron_assault_bot") { } - - struct npc_mimiron_assault_botAI : public ScriptedAI - { - npc_mimiron_assault_botAI(Creature* creature) : ScriptedAI(creature) - { - magneticTimer = 14000; - } - - uint32 magneticTimer; - - void UpdateAI(uint32 diff) override - { - if (me->HasUnitState(UNIT_STATE_ROOT)) - if (Unit* newTarget = SelectTarget(SELECT_TARGET_NEAREST, 0, 30.0f, true)) - { - me->DeleteThreatList(); - AttackStart(newTarget); - } - - if (magneticTimer <= diff) - { - DoCastVictim(SPELL_MAGNETIC_FIELD); - me->ClearUnitState(UNIT_STATE_CASTING); - magneticTimer = 30000; - } - else magneticTimer -= diff; - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class npc_mimiron_emergency_fire_bot : public CreatureScript -{ - public: - npc_mimiron_emergency_fire_bot() : CreatureScript("npc_mimiron_emergency_fire_bot") { } - - struct npc_mimiron_emergency_fire_botAI : public ScriptedAI - { - npc_mimiron_emergency_fire_botAI(Creature* creature) : ScriptedAI(creature) - { - me->SetReactState(REACT_PASSIVE); - watersprayTimer = 7000; - isWaterSprayReady = true; - moveNew = true; - } - - uint32 watersprayTimer; - bool isWaterSprayReady; - bool moveNew; - - uint32 GetData(uint32 id) const override - { - if (id == DATA_WATERSPRAY) - return isWaterSprayReady; - if (id == DATA_MOVE_NEW) - return moveNew; - return 0; - } - - void SetData(uint32 id, uint32 data) override - { - if (id == DATA_WATERSPRAY) - isWaterSprayReady = false; - else if (id == DATA_MOVE_NEW) - moveNew = data; - } - - void UpdateAI(uint32 diff) override - { - if (!isWaterSprayReady) - { - if (watersprayTimer <= diff) - { - isWaterSprayReady = true; - watersprayTimer = urand(7000, 9000); - } - else watersprayTimer -= diff; - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class npc_mimiron_computer : public CreatureScript -{ - public: - npc_mimiron_computer() : CreatureScript("npc_mimiron_computer") { } - - struct npc_mimiron_computerAI : public ScriptedAI - { - npc_mimiron_computerAI(Creature* creature) : ScriptedAI(creature) - { - instance = me->GetInstanceScript(); - } - - InstanceScript* instance; - EventMap events; - - void DoAction(int32 action) override - { - switch (action) - { - case DO_ACTIVATE_COMPUTER: - Talk(SAY_SELF_DESTRUCT_INITIATED); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_10, 3000); - break; - case DO_DEACTIVATE_COMPUTER: - Talk(SAY_SELF_DESTRUCT_TERMINATED); - me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_AURA); - me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_VISUAL); - events.Reset(); - break; - default: - break; - } - } - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SELF_DESTRUCT_10: - Talk(SAY_SELF_DESTRUCT_10); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->DoAction(DO_ACTIVATE_HARD_MODE); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_9, 60000); - break; - case EVENT_SELF_DESTRUCT_9: - Talk(SAY_SELF_DESTRUCT_9); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_8, 60000); - break; - case EVENT_SELF_DESTRUCT_8: - Talk(SAY_SELF_DESTRUCT_8); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_7, 60000); - break; - case EVENT_SELF_DESTRUCT_7: - Talk(SAY_SELF_DESTRUCT_7); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_6, 60000); - break; - case EVENT_SELF_DESTRUCT_6: - Talk(SAY_SELF_DESTRUCT_6); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_5, 60000); - break; - case EVENT_SELF_DESTRUCT_5: - Talk(SAY_SELF_DESTRUCT_5); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_4, 60000); - break; - case EVENT_SELF_DESTRUCT_4: - Talk(SAY_SELF_DESTRUCT_4); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_3, 60000); - break; - case EVENT_SELF_DESTRUCT_3: - Talk(SAY_SELF_DESTRUCT_3); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_2, 60000); - break; - case EVENT_SELF_DESTRUCT_2: - Talk(SAY_SELF_DESTRUCT_2); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_1, 60000); - break; - case EVENT_SELF_DESTRUCT_1: - Talk(SAY_SELF_DESTRUCT_1); - events.ScheduleEvent(EVENT_SELF_DESTRUCT_FINALIZED, 60000); - break; - case EVENT_SELF_DESTRUCT_FINALIZED: - Talk(SAY_SELF_DESTRUCT_FINALIZED); - if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON))) - mimiron->AI()->DoAction(DO_ACTIVATE_SELF_DESTRUCT); - DoCast(me, SPELL_SELF_DESTRUCTION_AURA); - DoCast(me, SPELL_SELF_DESTRUCTION_VISUAL); - break; - default: - break; - } - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class npc_mimiron_flames : public CreatureScript -{ - public: - npc_mimiron_flames() : CreatureScript("npc_mimiron_flames") { } - - struct npc_mimiron_flamesAI : public ScriptedAI - { - npc_mimiron_flamesAI(Creature* creature) : ScriptedAI(creature) - { - instance = me->GetInstanceScript(); - timer = 4000; - spawnedFlames = false; - } - - uint32 timer; - bool spawnedFlames; - InstanceScript* instance; - - void UpdateAI(uint32 diff) override - { - if (instance->GetBossState(BOSS_MIMIRON) != IN_PROGRESS) - me->DespawnOrUnsummon(); - if (!spawnedFlames) - { - if (timer <= diff) - { - DoCastAOE(SPELL_SUMMON_FLAMES_SPREAD_TRIGGER); - spawnedFlames = true; - } - else timer -= diff; - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class npc_mimiron_frost_bomb : public CreatureScript -{ - public: - npc_mimiron_frost_bomb() : CreatureScript("npc_mimiron_frost_bomb") { } - - struct npc_mimiron_frost_bombAI : public ScriptedAI - { - npc_mimiron_frost_bombAI(Creature* creature) : ScriptedAI(creature) - { - timer = 10000; - exploded = false; - } - - uint32 timer; - bool exploded; - - void UpdateAI(uint32 diff) override - { - if (timer <= diff) - { - if (!exploded) - { - DoCastAOE(SPELL_FROST_BOMB_EXPLOSION); - timer = 3000; - exploded = true; - } - else - { - DoCastAOE(SPELL_CLEAR_FIRES); - me->DespawnOrUnsummon(3000); - timer = 10000; - } - } - else timer -= diff; - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class npc_mimiron_proximity_mine : public CreatureScript -{ - public: - npc_mimiron_proximity_mine() : CreatureScript("npc_mimiron_proximity_mine") { } - - struct npc_mimiron_proximity_mineAI : public ScriptedAI - { - npc_mimiron_proximity_mineAI(Creature* creature) : ScriptedAI(creature) - { - explosionTimer = 35000; - boom = false; - armed = false; - } - - uint32 explosionTimer; - bool boom; - bool armed; - - void UpdateAI(uint32 diff) override - { - if (!boom) - { - if (explosionTimer <= 33500 && !armed) - { - DoCast(me, SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER); - armed = true; - } - if (explosionTimer <= diff) - { - if (me->HasAura(SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER)) - DoCastAOE(SPELL_PROXIMITY_MINE_EXPLOSION); - boom = true; - me->DespawnOrUnsummon(1000); - } - else explosionTimer -= diff; - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetUlduarAI(creature); - } -}; - -class go_mimiron_hardmode_button : public GameObjectScript -{ -public: - go_mimiron_hardmode_button() : GameObjectScript("go_mimiron_hardmode_button") { } - - bool OnGossipHello(Player* /*player*/, GameObject* go) - { - InstanceScript* instance = go->GetInstanceScript(); - - if (!instance) - return false; - - if (Creature* computer = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_COMPUTER))) - computer->AI()->DoAction(DO_ACTIVATE_COMPUTER); - go->SetGoState(GO_STATE_ACTIVE); - go->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_NOT_SELECTABLE); - return true; - } -}; - -// 63801 Bomb Bot -class spell_mimiron_bomb_bot : public SpellScriptLoader -{ - public: - spell_mimiron_bomb_bot() : SpellScriptLoader("spell_mimiron_bomb_bot") { } - - class spell_mimiron_bomb_bot_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_bomb_bot_SpellScript); - - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (GetHitPlayer()) - if (InstanceScript* instance = GetCaster()->GetInstanceScript()) - if (Creature* mkii = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_LEVIATHAN_MK_II))) - mkii->AI()->SetData(DATA_SETUP_BOMB, 0); - } - - void HandleDespawn(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit()->IsSummon()) - { - GetHitUnit()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); - GetHitUnit()->ToTempSummon()->DespawnOrUnsummon(1000); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_bomb_bot_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_bomb_bot_SpellScript::HandleDespawn, EFFECT_1, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_bomb_bot_SpellScript(); - } -}; - -// 65192 - Flame Suppressant, 65224 - Clear Fires, 65354 - Clear Fires, 64619 - Water Spray -class spell_mimiron_clear_fires : public SpellScriptLoader -{ - public: - spell_mimiron_clear_fires() : SpellScriptLoader("spell_mimiron_clear_fires") { } - - class spell_mimiron_clear_fires_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_clear_fires_SpellScript); - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit()->IsSummon()) - GetHitUnit()->ToTempSummon()->DespawnOrUnsummon(); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_clear_fires_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_clear_fires_SpellScript(); - } -}; - -// 64463 - Despawn Assault Bots -class spell_mimiron_despawn_assault_bots : public SpellScriptLoader -{ - public: - spell_mimiron_despawn_assault_bots() : SpellScriptLoader("spell_mimiron_despawn_assault_bots") { } - - class spell_mimiron_despawn_assault_bots_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_despawn_assault_bots_SpellScript); - - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit()->IsSummon()) - GetHitUnit()->ToTempSummon()->DespawnOrUnsummon(); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_despawn_assault_bots_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_despawn_assault_bots_SpellScript(); - } -}; - -// 64626 - Explosion -class spell_mimiron_frost_bomb_explosion : public SpellScriptLoader -{ - public: - spell_mimiron_frost_bomb_explosion() : SpellScriptLoader("spell_mimiron_frost_bomb_explosion") { } - - class spell_mimiron_frost_bomb_explosion_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_frost_bomb_explosion_SpellScript); - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->RemoveAurasDueToSpell(SPELL_FLAMES_PERIODIC_TRIGGER); - } - - void HandleUnaura(SpellEffIndex /*effIndex*/) - { - GetCaster()->RemoveAurasDueToSpell(SPELL_FROST_BOMB_LINKED); - } - - void Register() override - { - OnEffectHit += SpellEffectFn(spell_mimiron_frost_bomb_explosion_SpellScript::HandleUnaura, EFFECT_2, SPELL_EFFECT_DUMMY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_frost_bomb_explosion_SpellScript::HandleDummy, EFFECT_2, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_frost_bomb_explosion_SpellScript(); - } -}; - -// 64618 - Fire Search -class spell_mimiron_fire_search : public SpellScriptLoader -{ - public: - spell_mimiron_fire_search() : SpellScriptLoader("spell_mimiron_fire_search") { } - - class spell_mimiron_fire_search_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_fire_search_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_WATER_SPRAY)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - { - GetCaster()->GetMotionMaster()->MoveRandom(15.0f); - return; - } - - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.clear(); - targets.push_back(target); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - Unit* caster = GetCaster(); - - if (caster->GetAI()) - { - if (caster->GetDistance2d(GetHitUnit()) <= 15.0f && caster->GetAI()->GetData(DATA_WATERSPRAY)) - { - caster->CastSpell(GetHitUnit(), SPELL_WATER_SPRAY, true); - caster->GetAI()->SetData(DATA_WATERSPRAY, 0); - caster->GetAI()->SetData(DATA_MOVE_NEW, 1); - } - else if (caster->GetAI()->GetData(DATA_MOVE_NEW)) - { - caster->GetMotionMaster()->MoveChase(GetHitUnit()); - caster->GetAI()->SetData(DATA_MOVE_NEW, 0); - } - } - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_fire_search_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_fire_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_fire_search_SpellScript(); - } -}; - -// 64570 - Flame Suppressant -class spell_mimiron_flame_suppressant : public SpellScriptLoader -{ - public: - spell_mimiron_flame_suppressant() : SpellScriptLoader("spell_mimiron_flame_suppressant") { } - - class spell_mimiron_flame_suppressant_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_flame_suppressant_SpellScript); - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->RemoveAurasDueToSpell(SPELL_FLAMES_PERIODIC_TRIGGER); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_flame_suppressant_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_flame_suppressant_SpellScript(); - } -}; - -// 64436 - Magnetic Core -class spell_mimiron_magnetic_core : public SpellScriptLoader -{ - public: - spell_mimiron_magnetic_core() : SpellScriptLoader("spell_mimiron_magnetic_core") { } - - class spell_mimiron_magnetic_core_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_magnetic_core_SpellScript); - - void FilterTargets(std::list& targets) - { - targets.remove_if(AerialTargetSelector()); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_magnetic_core_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_magnetic_core_SpellScript(); - } - - class spell_mimiron_magnetic_core_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_magnetic_core_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_MAGNETIC_CORE_VISUAL)) - return false; - return true; - } - - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - if (target->GetAI()) - target->GetAI()->DoAction(DO_DISABLE_AERIAL); - - target->CastSpell(target, SPELL_MAGNETIC_CORE_VISUAL, true); - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - if (target->GetAI()) - target->GetAI()->DoAction(DO_ENABLE_AERIAL); - - target->RemoveAurasDueToSpell(SPELL_MAGNETIC_CORE_VISUAL); - } - - void OnRemoveSelf(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (GetTarget()->ToCreature()) - GetTarget()->ToCreature()->DespawnOrUnsummon(); - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_mimiron_magnetic_core_AuraScript::OnApply, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_mimiron_magnetic_core_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_mimiron_magnetic_core_AuraScript::OnRemoveSelf, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_magnetic_core_AuraScript(); - } -}; - -// 63667 - Napalm Shell -class spell_mimiron_napalm_shell : public SpellScriptLoader -{ - public: - spell_mimiron_napalm_shell() : SpellScriptLoader("spell_mimiron_napalm_shell") { } - - class spell_mimiron_napalm_shell_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_napalm_shell_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_NAPALM_SHELL)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.remove_if(Trinity::AllWorldObjectsInRange(GetCaster(), 15.0f)); - - if (!targets.empty()) - target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.clear(); - targets.push_back(target); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell(GetHitUnit(), SPELL_NAPALM_SHELL); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_napalm_shell_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_napalm_shell_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_napalm_shell_SpellScript(); - } -}; - -// 63274 - P3Wx2 Laser Barrage -- This should be removed when channel track target implementation is properly functioning. -class spell_mimiron_p3wx2_laser_barrage : public SpellScriptLoader -{ - public: - spell_mimiron_p3wx2_laser_barrage() : SpellScriptLoader("spell_mimiron_p3wx2_laser_barrage") { } - - class spell_mimiron_p3wx2_laser_barrage_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_p3wx2_laser_barrage_SpellScript); - - void OnHit(SpellEffIndex /*effIndex*/) - { - GetCaster()->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, GetHitUnit()->GetGUID()); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_p3wx2_laser_barrage_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_p3wx2_laser_barrage_SpellScript(); - } -}; - -// 64542 - Plasma Blast -class spell_mimiron_plasma_blast : public SpellScriptLoader -{ - public: - spell_mimiron_plasma_blast() : SpellScriptLoader("spell_mimiron_plasma_blast") { } - - class spell_mimiron_plasma_blast_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_plasma_blast_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_PLASMA_BLAST)) - return false; - return true; - } - - bool Load() override - { - return GetCaster()->GetVehicleKit(); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (Unit* caster = GetCaster()->GetVehicleKit()->GetPassenger(3)) - caster->CastSpell(GetHitUnit(), SPELL_PLASMA_BLAST); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_plasma_blast_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_plasma_blast_SpellScript(); - } -}; - -// 66351 - Explosion -class spell_mimiron_proximity_explosion : public SpellScriptLoader -{ - public: - spell_mimiron_proximity_explosion() : SpellScriptLoader("spell_mimiron_proximity_explosion") { } - - class spell_mimiron_proximity_explosion_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_proximity_explosion_SpellScript); - - void OnHit(SpellEffIndex /*effIndex*/) - { - if (GetHitPlayer()) - if (InstanceScript* instance = GetCaster()->GetInstanceScript()) - if (Creature* mkII = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_LEVIATHAN_MK_II))) - mkII->AI()->SetData(DATA_SETUP_MINE, 0); - } - - void HandleAura(SpellEffIndex /*effIndex*/) - { - GetCaster()->RemoveAurasDueToSpell(SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_proximity_explosion_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_proximity_explosion_SpellScript::HandleAura, EFFECT_1, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_proximity_explosion_SpellScript(); - } -}; - -// 63027 - Proximity Mines -class spell_mimiron_proximity_mines : public SpellScriptLoader -{ - public: - spell_mimiron_proximity_mines() : SpellScriptLoader("spell_mimiron_proximity_mines") { } - - class spell_mimiron_proximity_mines_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_proximity_mines_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_PROXIMITY_MINE)) - return false; - return true; - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - for (uint8 i = 0; i < 10; ++i) - GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_PROXIMITY_MINE, true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_proximity_mines_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_proximity_mines_SpellScript(); - } -}; - -// 65346 - Proximity Mine -class spell_mimiron_proximity_trigger : public SpellScriptLoader -{ - public: - spell_mimiron_proximity_trigger() : SpellScriptLoader("spell_mimiron_proximity_trigger") { } - - class spell_mimiron_proximity_trigger_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_proximity_trigger_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_PROXIMITY_MINE_EXPLOSION)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - targets.remove(GetExplTargetWorldObject()); - - if (targets.empty()) - FinishCast(SPELL_FAILED_NO_VALID_TARGETS); - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell((Unit*)NULL, SPELL_PROXIMITY_MINE_EXPLOSION, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_proximity_trigger_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHit += SpellEffectFn(spell_mimiron_proximity_trigger_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_proximity_trigger_SpellScript(); - } -}; - -// 63382 - Rapid Burst -class spell_mimiron_rapid_burst : public SpellScriptLoader -{ - public: - spell_mimiron_rapid_burst() : SpellScriptLoader("spell_mimiron_rapid_burst") { } - - class spell_mimiron_rapid_burst_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_rapid_burst_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_RAPID_BURST_LEFT) || !sSpellMgr->GetSpellInfo(SPELL_RAPID_BURST_RIGHT)) - return false; - return true; - } - - void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (GetTarget()->IsSummon()) - GetTarget()->ToTempSummon()->DespawnOrUnsummon(); - } - - void HandleDummyTick(AuraEffect const* aurEff) - { - if (GetCaster()) - GetCaster()->CastSpell(GetTarget(), aurEff->GetTickNumber() % 2 == 0 ? SPELL_RAPID_BURST_RIGHT : SPELL_RAPID_BURST_LEFT, true, NULL, aurEff); - } - - void Register() override - { - AfterEffectRemove += AuraEffectApplyFn(spell_mimiron_rapid_burst_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_rapid_burst_AuraScript::HandleDummyTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_rapid_burst_AuraScript(); - } -}; - -// 64402 - Rocket Strike, 65034 - Rocket Strike -class spell_mimiron_rocket_strike : public SpellScriptLoader -{ - public: - spell_mimiron_rocket_strike() : SpellScriptLoader("spell_mimiron_rocket_strike") { } - - class spell_mimiron_rocket_strike_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_rocket_strike_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SCRIPT_EFFECT_ROCKET_STRIKE)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - if (m_scriptSpellId == SPELL_ROCKET_STRIKE_LEFT && GetCaster()->IsVehicle()) - if (WorldObject* target = GetCaster()->GetVehicleKit()->GetPassenger(6)) - { - targets.clear(); - targets.push_back(target); - } - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell((Unit*)NULL, SPELL_SCRIPT_EFFECT_ROCKET_STRIKE, true, NULL, NULL, GetCaster()->GetGUID()); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_rocket_strike_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_rocket_strike_SpellScript(); - } -}; - -// 63041 - Rocket Strike -class spell_mimiron_rocket_strike_damage : public SpellScriptLoader -{ - public: - spell_mimiron_rocket_strike_damage() : SpellScriptLoader("spell_mimiron_rocket_strike_damage") { } - - class spell_mimiron_rocket_strike_damage_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_rocket_strike_damage_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_NOT_SO_FRIENDLY_FIRE)) - return false; - return true; - } - - void HandleDespawn(SpellEffIndex /*effIndex*/) - { - if (GetCaster()->IsSummon()) - GetCaster()->ToTempSummon()->DespawnOrUnsummon(1000); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (GetHitPlayer()) - if (InstanceScript* instance = GetCaster()->GetInstanceScript()) - if (Creature* mkii = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_LEVIATHAN_MK_II))) - mkii->AI()->SetData(DATA_SETUP_ROCKET, 0); - } - - void HandleFriendlyFire(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell((Unit*)NULL, SPELL_NOT_SO_FRIENDLY_FIRE, true); - } - - void Register() override - { - OnEffectHit += SpellEffectFn(spell_mimiron_rocket_strike_damage_SpellScript::HandleDespawn, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_damage_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_damage_SpellScript::HandleFriendlyFire, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_rocket_strike_damage_SpellScript(); - } -}; - -// 63681 - Rocket Strike -class spell_mimiron_rocket_strike_target_select : public SpellScriptLoader -{ - public: - spell_mimiron_rocket_strike_target_select() : SpellScriptLoader("spell_mimiron_rocket_strike_target_select") { } - - class spell_mimiron_rocket_strike_target_select_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_rocket_strike_target_select_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ROCKET_STRIKE)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.remove_if(Trinity::AllWorldObjectsInRange(GetCaster(), 15.0f)); - - if (!targets.empty()) - target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.clear(); - targets.push_back(target); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - InstanceScript* instance = GetCaster()->GetInstanceScript(); - GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ROCKET_STRIKE, true, NULL, NULL, instance ? instance->GetData64(DATA_VX_001) : GetCaster()->GetGUID()); - GetCaster()->SetDisplayId(11686); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_rocket_strike_target_select_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_rocket_strike_target_select_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_rocket_strike_target_select_SpellScript(); - } -}; - -// 64383 - Self Repair -class spell_mimiron_self_repair : public SpellScriptLoader -{ - public: - spell_mimiron_self_repair() : SpellScriptLoader("spell_mimiron_self_repair") { } - - class spell_mimiron_self_repair_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_self_repair_SpellScript); - - void HandleScript() - { - if (GetCaster()->GetAI()) - GetCaster()->GetAI()->DoAction(DO_ASSEMBLED_COMBAT); - } - - void Register() override - { - AfterHit += SpellHitFn(spell_mimiron_self_repair_SpellScript::HandleScript); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_self_repair_SpellScript(); - } -}; - -// 63414 - Spinning Up -- This should be removed when channel track target implementation is properly functioning. -class spell_mimiron_spinning_up : public SpellScriptLoader -{ - public: - spell_mimiron_spinning_up() : SpellScriptLoader("spell_mimiron_spinning_up") { } - - class spell_mimiron_spinning_up_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_spinning_up_SpellScript); - - void OnHit(SpellEffIndex /*effIndex*/) - { - if (GetHitUnit() != GetCaster()) - GetCaster()->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, GetHitUnit()->GetGUID()); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_spinning_up_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_spinning_up_SpellScript(); - } -}; - -// 64426 - Summon Scrap Bot -class spell_mimiron_summon_assault_bot : public SpellScriptLoader -{ - public: - spell_mimiron_summon_assault_bot() : SpellScriptLoader("spell_mimiron_summon_assault_bot") { } - - class spell_mimiron_summon_assault_bot_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_summon_assault_bot_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ASSAULT_BOT)) - return false; - return true; - } - - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - if (InstanceScript* instance = caster->GetInstanceScript()) - if (instance->GetBossState(BOSS_MIMIRON) == IN_PROGRESS) - caster->CastSpell(caster, SPELL_SUMMON_ASSAULT_BOT, false, NULL, aurEff, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)); - } - - void Register() override - { - OnEffectRemove += AuraEffectRemoveFn(spell_mimiron_summon_assault_bot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_summon_assault_bot_AuraScript(); - } -}; - -// 64425 - Summon Scrap Bot Trigger -class spell_mimiron_summon_assault_bot_target : public SpellScriptLoader -{ - public: - spell_mimiron_summon_assault_bot_target() : SpellScriptLoader("spell_mimiron_summon_assault_bot_target") { } - - class spell_mimiron_summon_assault_bot_target_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_assault_bot_target_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ASSAULT_BOT_DUMMY)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.clear(); - targets.push_back(target); - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_ASSAULT_BOT_DUMMY, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_assault_bot_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_assault_bot_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_assault_bot_target_SpellScript(); - } -}; - -// 64621 - Summon Fire Bot -class spell_mimiron_summon_fire_bot : public SpellScriptLoader -{ - public: - spell_mimiron_summon_fire_bot() : SpellScriptLoader("spell_mimiron_summon_fire_bot") { } - - class spell_mimiron_summon_fire_bot_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_summon_fire_bot_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FIRE_BOT)) - return false; - - return true; - } - - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - if (InstanceScript* instance = caster->GetInstanceScript()) - if (instance->GetBossState(BOSS_MIMIRON) == IN_PROGRESS) - caster->CastSpell(caster, SPELL_SUMMON_FIRE_BOT, false, NULL, aurEff, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)); - } - - void Register() override - { - OnEffectRemove += AuraEffectRemoveFn(spell_mimiron_summon_fire_bot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_summon_fire_bot_AuraScript(); - } -}; - -// 64620 - Summon Fire Bot Trigger -class spell_mimiron_summon_fire_bot_target : public SpellScriptLoader -{ - public: - spell_mimiron_summon_fire_bot_target() : SpellScriptLoader("spell_mimiron_summon_fire_bot_target") { } - - class spell_mimiron_summon_fire_bot_target_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_fire_bot_target_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FIRE_BOT_DUMMY)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - Trinity::Containers::RandomResizeList(targets, 3); - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_FIRE_BOT_DUMMY, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_fire_bot_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_fire_bot_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_fire_bot_target_SpellScript(); - } -}; - -// 64567 - Summon Flames Initial -class spell_mimiron_summon_flames_initial : public SpellScriptLoader -{ - public: - spell_mimiron_summon_flames_initial() : SpellScriptLoader("spell_mimiron_summon_flames_initial") { } - - class spell_mimiron_summon_flames_initial_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_flames_initial_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FLAMES_INITIAL)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - Trinity::Containers::RandomResizeList(targets, 3); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_FLAMES_INITIAL, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_flames_initial_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_flames_initial_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_flames_initial_SpellScript(); - } -}; - -// 64562 - Summon Flames Spread Trigger -class spell_mimiron_summon_flames_spread : public SpellScriptLoader -{ - public: - spell_mimiron_summon_flames_spread() : SpellScriptLoader("spell_mimiron_summon_flames_spread") { } - - class spell_mimiron_summon_flames_spread_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_flames_spread_SpellScript); - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - WorldObject* target = targets.front(); - - for (std::list::const_iterator iter = targets.begin(); iter != targets.end(); iter++) - if (GetCaster()->GetDistance2d(*iter) < GetCaster()->GetDistance2d(target)) - target = *iter; - - targets.clear(); - targets.push_back(target); - } - - void OnHit(SpellEffIndex /*effIndex*/) - { - GetCaster()->SetInFront(GetHitUnit()); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_flames_spread_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_flames_spread_SpellScript::OnHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_flames_spread_SpellScript(); - } - - class spell_mimiron_summon_flames_spread_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_summon_flames_spread_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FLAMES_SPREAD)) - return false; - return true; - } - - void HandleTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - if (caster->HasAura(SPELL_FLAMES_PERIODIC_TRIGGER)) - caster->CastSpell(GetTarget(), SPELL_SUMMON_FLAMES_SPREAD, true); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_summon_flames_spread_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_summon_flames_spread_AuraScript(); - } -}; - -// 64627 - Frost Bomb -class spell_mimiron_summon_frost_bomb : public SpellScriptLoader -{ - public: - spell_mimiron_summon_frost_bomb() : SpellScriptLoader("spell_mimiron_summon_frost_bomb") { } - - class spell_mimiron_summon_frost_bomb_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_frost_bomb_SpellScript); - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->RemoveAurasDueToSpell(SPELL_FLAMES_PERIODIC_TRIGGER); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_frost_bomb_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_frost_bomb_SpellScript(); - } -}; - -// 64623 - Frost Bomb -class spell_mimiron_summon_frost_bomb_target : public SpellScriptLoader -{ - public: - spell_mimiron_summon_frost_bomb_target() : SpellScriptLoader("spell_mimiron_summon_frost_bomb_target") { } - - class spell_mimiron_summon_frost_bomb_target_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_frost_bomb_target_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_FROST_BOMB)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - targets.remove_if(Trinity::AllWorldObjectsInRange(GetCaster(), 15.0f)); - - if (targets.empty()) - return; - - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.clear(); - targets.push_back(target); - } - - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_FROST_BOMB, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_frost_bomb_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_frost_bomb_target_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_frost_bomb_target_SpellScript(); - } -}; - -// 64398 - Summon Scrap Bot -class spell_mimiron_summon_junk_bot : public SpellScriptLoader -{ - public: - spell_mimiron_summon_junk_bot() : SpellScriptLoader("spell_mimiron_summon_junk_bot") { } - - class spell_mimiron_summon_junk_bot_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_summon_junk_bot_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_JUNK_BOT)) - return false; - return true; - } - - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - if (InstanceScript* instance = caster->GetInstanceScript()) - if (instance->GetBossState(BOSS_MIMIRON) == IN_PROGRESS) - caster->CastSpell(caster, SPELL_SUMMON_JUNK_BOT, false, NULL, aurEff, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)); - } - - void Register() override - { - OnEffectRemove += AuraEffectRemoveFn(spell_mimiron_summon_junk_bot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_summon_junk_bot_AuraScript(); - } -}; - -// 63820 - Summon Scrap Bot Trigger -class spell_mimiron_summon_junk_bot_target : public SpellScriptLoader -{ - public: - spell_mimiron_summon_junk_bot_target() : SpellScriptLoader("spell_mimiron_summon_junk_bot_target") { } - - class spell_mimiron_summon_junk_bot_target_SpellScript : public SpellScript - { - PrepareSpellScript(spell_mimiron_summon_junk_bot_target_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_JUNK_BOT_DUMMY)) - return false; - return true; - } - - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; - - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - - targets.clear(); - targets.push_back(target); - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_JUNK_BOT_DUMMY, true); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mimiron_summon_junk_bot_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_mimiron_summon_junk_bot_target_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_mimiron_summon_junk_bot_target_SpellScript(); - } -}; - -// 63339 - Weld -class spell_mimiron_weld : public SpellScriptLoader -{ - public: - spell_mimiron_weld() : SpellScriptLoader("spell_mimiron_weld") { } - - class spell_mimiron_weld_AuraScript : public AuraScript - { - PrepareAuraScript(spell_mimiron_weld_AuraScript); - - void HandleTick(AuraEffect const* aurEff) - { - Unit* caster = GetTarget(); - if (Unit* vehicle = caster->GetVehicleBase()) - { - if (aurEff->GetTickNumber() % 5 == 0) - caster->CastSpell(vehicle, repairSpells[urand(0, 3)]); - caster->SetFacingToObject(vehicle); - } - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_weld_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_mimiron_weld_AuraScript(); - } -}; - -class achievement_setup_boom : public AchievementCriteriaScript -{ - public: - achievement_setup_boom() : AchievementCriteriaScript("achievement_setup_boom") { } - - bool OnCheck(Player* /*source*/, Unit* target) - { - return target && target->GetAI()->GetData(DATA_SETUP_BOMB); - } -}; - -class achievement_setup_mine : public AchievementCriteriaScript -{ - public: - achievement_setup_mine() : AchievementCriteriaScript("achievement_setup_mine") { } - - bool OnCheck(Player* /*source*/, Unit* target) - { - return target && target->GetAI()->GetData(DATA_SETUP_MINE); - } -}; - -class achievement_setup_rocket : public AchievementCriteriaScript -{ - public: - achievement_setup_rocket() : AchievementCriteriaScript("achievement_setup_rocket") { } - - bool OnCheck(Player* /*source*/, Unit* target) - { - return target && target->GetAI()->GetData(DATA_SETUP_ROCKET); - } -}; - -class achievement_firefighter : public AchievementCriteriaScript -{ - public: - achievement_firefighter() : AchievementCriteriaScript("achievement_firefighter") { } - - bool OnCheck(Player* /*source*/, Unit* target) - { - return target && target->GetAI()->GetData(DATA_FIREFIGHTER); - } -}; - -void AddSC_boss_mimiron() -{ - new boss_aerial_command_unit(); - new boss_leviathan_mk_ii(); - new boss_mimiron(); - new boss_vx_001(); - - new npc_magnetic_core(); - new npc_mimiron_assault_bot(); - new npc_mimiron_emergency_fire_bot(); - new npc_mimiron_computer(); - new npc_mimiron_flames(); - new npc_mimiron_frost_bomb(); - new npc_mimiron_proximity_mine(); - - new go_mimiron_hardmode_button(); - - new spell_mimiron_bomb_bot(); - new spell_mimiron_clear_fires(); - new spell_mimiron_despawn_assault_bots(); - new spell_mimiron_fire_search(); - new spell_mimiron_flame_suppressant(); - new spell_mimiron_frost_bomb_explosion(); - new spell_mimiron_magnetic_core(); - new spell_mimiron_napalm_shell(); - new spell_mimiron_p3wx2_laser_barrage(); - new spell_mimiron_plasma_blast(); - new spell_mimiron_proximity_explosion(); - new spell_mimiron_proximity_mines(); - new spell_mimiron_proximity_trigger(); - new spell_mimiron_rapid_burst(); - new spell_mimiron_rocket_strike(); - new spell_mimiron_rocket_strike_damage(); - new spell_mimiron_rocket_strike_target_select(); - new spell_mimiron_self_repair(); - new spell_mimiron_spinning_up(); - new spell_mimiron_summon_assault_bot(); - new spell_mimiron_summon_assault_bot_target(); - new spell_mimiron_summon_fire_bot(); - new spell_mimiron_summon_fire_bot_target(); - new spell_mimiron_summon_flames_initial(); - new spell_mimiron_summon_flames_spread(); - new spell_mimiron_summon_frost_bomb(); - new spell_mimiron_summon_frost_bomb_target(); - new spell_mimiron_summon_junk_bot(); - new spell_mimiron_summon_junk_bot_target(); - new spell_mimiron_weld(); - - new achievement_setup_boom(); - new achievement_setup_mine(); - new achievement_setup_rocket(); - new achievement_firefighter(); + new spell_ulduar_proximity_mines(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 257518d998b..6437a76ee95 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -32,9 +32,6 @@ static DoorData const doorData[] = { GO_HODIR_ENTRANCE, BOSS_HODIR, DOOR_TYPE_ROOM, BOUNDARY_E }, { GO_HODIR_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, { GO_HODIR_ICE_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_W }, - { GO_MIMIRON_DOOR_1, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_W }, - { GO_MIMIRON_DOOR_2, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_E }, - { GO_MIMIRON_DOOR_3, BOSS_MIMIRON, DOOR_TYPE_ROOM, BOUNDARY_S }, { GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE, BOUNDARY_E }, { GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S }, { GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, @@ -73,14 +70,11 @@ class instance_ulduar : public InstanceMapScript uint64 AssemblyGUIDs[3]; uint64 KologarnGUID; uint64 AuriayaGUID; + uint64 MimironGUID; uint64 HodirGUID; uint64 ThorimGUID; uint64 FreyaGUID; uint64 ElderGUIDs[3]; - uint64 MimironGUID; - uint64 MimironVehicleGUIDs[3]; - uint64 MimironComputerGUID; - uint64 MimironWorldTriggerGUID; uint64 VezaxGUID; uint64 YoggSaronGUID; uint64 VoiceOfYoggSaronGUID; @@ -98,9 +92,6 @@ class instance_ulduar : public InstanceMapScript uint64 ThorimChestGUID; uint64 HodirRareCacheGUID; uint64 HodirChestGUID; - uint64 MimironTramGUID; - uint64 MimironElevatorGUID; - uint64 MimironButtonGUID; uint64 BrainRoomDoorGUIDs[3]; uint64 AlgalonSigilDoorGUID[3]; uint64 AlgalonFloorGUID[2]; @@ -135,8 +126,6 @@ class instance_ulduar : public InstanceMapScript KologarnGUID = 0; AuriayaGUID = 0; MimironGUID = 0; - MimironComputerGUID = 0; - MimironWorldTriggerGUID = 0; HodirGUID = 0; ThorimGUID = 0; FreyaGUID = 0; @@ -151,9 +140,6 @@ class instance_ulduar : public InstanceMapScript ThorimChestGUID = 0; HodirRareCacheGUID = 0; HodirChestGUID = 0; - MimironTramGUID = 0; - MimironElevatorGUID = 0; - MimironButtonGUID = 0; LeviathanGateGUID = 0; AlgalonUniverseGUID = 0; AlgalonTrapdoorGUID = 0; @@ -180,7 +166,6 @@ class instance_ulduar : public InstanceMapScript memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs)); memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs)); memset(ElderGUIDs, 0, sizeof(ElderGUIDs)); - memset(MimironVehicleGUIDs, 0, sizeof(MimironVehicleGUIDs)); memset(BrainRoomDoorGUIDs, 0, sizeof(BrainRoomDoorGUIDs)); memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs)); memset(_summonObservationRingKeeper, false, sizeof(_summonObservationRingKeeper)); @@ -304,6 +289,9 @@ class instance_ulduar : public InstanceMapScript case NPC_AURIAYA: AuriayaGUID = creature->GetGUID(); break; + case NPC_MIMIRON: + MimironGUID = creature->GetGUID(); + break; // Hodir case NPC_HODIR: @@ -366,28 +354,6 @@ class instance_ulduar : public InstanceMapScript creature->DespawnOrUnsummon(); break; - // Mimiron - case NPC_MIMIRON: - MimironGUID = creature->GetGUID(); - break; - case NPC_LEVIATHAN_MKII: - MimironVehicleGUIDs[0] = creature->GetGUID(); - if (GetBossState(BOSS_MIMIRON) == DONE) - creature->DespawnOrUnsummon(); - break; - case NPC_VX_001: - MimironVehicleGUIDs[1] = creature->GetGUID(); - break; - case NPC_AERIAL_COMMAND_UNIT: - MimironVehicleGUIDs[2] = creature->GetGUID(); - break; - case NPC_COMPUTER: - MimironComputerGUID = creature->GetGUID(); - break; - case NPC_WORLD_TRIGGER_MIMIRON: - MimironWorldTriggerGUID = creature->GetGUID(); - break; - case NPC_VEZAX: VezaxGUID = creature->GetGUID(); break; @@ -504,15 +470,6 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_CHEST: HodirChestGUID = gameObject->GetGUID(); break; - case GO_MIMIRON_TRAM: - MimironTramGUID = gameObject->GetGUID(); - break; - case GO_MIMIRON_ELEVATOR: - MimironElevatorGUID = gameObject->GetGUID(); - break; - case GO_MIMIRON_BUTTON: - MimironButtonGUID = gameObject->GetGUID(); - break; case GO_LEVIATHAN_GATE: LeviathanGateGUID = gameObject->GetGUID(); if (GetBossState(BOSS_LEVIATHAN) == DONE) @@ -525,9 +482,6 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_ENTRANCE: case GO_HODIR_DOOR: case GO_HODIR_ICE_DOOR: - case GO_MIMIRON_DOOR_1: - case GO_MIMIRON_DOOR_2: - case GO_MIMIRON_DOOR_3: case GO_VEZAX_DOOR: case GO_YOGG_SARON_DOOR: AddDoor(gameObject, true); @@ -612,9 +566,6 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_ENTRANCE: case GO_HODIR_DOOR: case GO_HODIR_ICE_DOOR: - case GO_MIMIRON_DOOR_1: - case GO_MIMIRON_DOOR_2: - case GO_MIMIRON_DOOR_3: case GO_VEZAX_DOOR: case GO_YOGG_SARON_DOOR: case GO_DOODAD_UL_SIGILDOOR_03: @@ -823,10 +774,6 @@ class instance_ulduar : public InstanceMapScript break; case DATA_UNBROKEN: Unbroken = bool(data); - break; - case DATA_MIMIRON_ELEVATOR: - if (GameObject* gameObject = instance->GetGameObject(MimironElevatorGUID)) - gameObject->SetGoState((GOState)data); break; case DATA_ILLUSION: illusion = data; @@ -899,6 +846,8 @@ class instance_ulduar : public InstanceMapScript return KologarnGUID; case BOSS_AURIAYA: return AuriayaGUID; + case BOSS_MIMIRON: + return MimironGUID; case BOSS_HODIR: return HodirGUID; case BOSS_THORIM: @@ -913,22 +862,6 @@ class instance_ulduar : public InstanceMapScript return ElderGUIDs[1]; case BOSS_STONEBARK: return ElderGUIDs[2]; - - // Mimiron - case BOSS_MIMIRON: - return MimironGUID; - case DATA_LEVIATHAN_MK_II: - return MimironVehicleGUIDs[0]; - case DATA_VX_001: - return MimironVehicleGUIDs[1]; - case DATA_AERIAL_COMMAND_UNIT: - return MimironVehicleGUIDs[2]; - case DATA_COMPUTER: - return MimironComputerGUID; - case DATA_MIMIRON_WORLD_TRIGGER: - return MimironWorldTriggerGUID; - case DATA_MIMIRON_BUTTON: - return MimironButtonGUID; case BOSS_VEZAX: return VezaxGUID; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 1c9fa7575d0..3544ff3c079 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -83,18 +83,6 @@ enum UlduarNPCs NPC_LEVIATHAN_MKII = 33432, NPC_VX_001 = 33651, NPC_AERIAL_COMMAND_UNIT = 33670, - NPC_ASSAULT_BOT = 34057, - NPC_BOMB_BOT = 33836, - NPC_JUNK_BOT = 33855, - NPC_EMERGENCY_FIRE_BOT = 34147, - NPC_FROST_BOMB = 34149, - NPC_BURST_TARGET = 34211, - NPC_FLAME = 34363, - NPC_FLAME_SPREAD = 34121, - NPC_DB_TARGET = 33576, - NPC_ROCKET_MIMIRON_VISUAL = 34050, - NPC_WORLD_TRIGGER_MIMIRON = 21252, - NPC_COMPUTER = 34143, // Freya's Keepers NPC_IRONBRANCH = 32913, @@ -216,18 +204,6 @@ enum UlduarGameObjects GO_THORIM_CHEST_HERO = 194315, GO_THORIM_CHEST = 194314, - // Mimiron - GO_MIMIRON_TRAM = 194675, - GO_MIMIRON_ELEVATOR = 194749, - GO_MIMIRON_BUTTON = 194739, - GO_MIMIRON_DOOR_1 = 194774, - GO_MIMIRON_DOOR_2 = 194775, - GO_MIMIRON_DOOR_3 = 194776, - GO_CACHE_OF_INNOVATION = 194789, - GO_CACHE_OF_INNOVATION_FIREFIGHTER = 194957, - GO_CACHE_OF_INNOVATION_HERO = 194956, - GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO = 194958, - // Vezax GO_VEZAX_DOOR = 194750, @@ -316,16 +292,6 @@ enum UlduarData // Hodir DATA_HODIR_RARE_CACHE, - // Mimiron - DATA_LEVIATHAN_MK_II, - DATA_VX_001, - DATA_AERIAL_COMMAND_UNIT, - DATA_COMPUTER, - DATA_MIMIRON_WORLD_TRIGGER, - DATA_MIMIRON_ELEVATOR, - DATA_MIMIRON_TRAM, - DATA_MIMIRON_BUTTON, - // Yogg-Saron DATA_VOICE_OF_YOGG_SARON, DATA_SARA, -- cgit v1.2.3 From 2a3546ca36468b81d673bdb27315006144af3165 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 1 Jul 2014 17:20:48 +0200 Subject: Core/Skills: Use SkillLineAbility.dbc to determine player initial spells - skill assignment done in a new table `playercreateinfo_skills` * Removed DK start skill hacks * Resolved missing skills in character skill tab Closes #12311 --- .../2014_07_01_00_characters_character_skills.sql | 4 + ...2014_07_01_02_world playercreateinfo_skills.sql | 90 ++++++++ src/server/game/DataStores/DBCEnums.h | 6 +- src/server/game/DataStores/DBCStores.cpp | 2 +- src/server/game/DataStores/DBCStructure.h | 19 +- src/server/game/Entities/Player/Player.cpp | 257 ++++++++++++--------- src/server/game/Entities/Player/Player.h | 15 +- src/server/game/Entities/Unit/Unit.cpp | 10 +- src/server/game/Globals/ObjectMgr.cpp | 131 ++++++++--- src/server/game/Globals/ObjectMgr.h | 2 +- src/server/game/Spells/SpellInfo.cpp | 2 +- src/server/game/Spells/SpellMgr.cpp | 2 +- src/server/scripts/Commands/cs_learn.cpp | 3 +- 13 files changed, 368 insertions(+), 175 deletions(-) create mode 100644 sql/updates/characters/2014_07_01_00_characters_character_skills.sql create mode 100644 sql/updates/world/2014_07_01_02_world playercreateinfo_skills.sql (limited to 'src/server/scripts') diff --git a/sql/updates/characters/2014_07_01_00_characters_character_skills.sql b/sql/updates/characters/2014_07_01_00_characters_character_skills.sql new file mode 100644 index 00000000000..1987adb064c --- /dev/null +++ b/sql/updates/characters/2014_07_01_00_characters_character_skills.sql @@ -0,0 +1,4 @@ +-- Set fist weapon skill equal to current unarmed skill value +UPDATE character_skills cs_unarmed INNER JOIN character_skills cs_fist ON cs_unarmed.guid = cs_fist.guid +SET cs_fist.value = cs_unarmed.value, cs_fist.max = cs_unarmed.max +WHERE cs_unarmed.skill = 162 AND cs_fist.skill = 473; diff --git a/sql/updates/world/2014_07_01_02_world playercreateinfo_skills.sql b/sql/updates/world/2014_07_01_02_world playercreateinfo_skills.sql new file mode 100644 index 00000000000..8eb452afa96 --- /dev/null +++ b/sql/updates/world/2014_07_01_02_world playercreateinfo_skills.sql @@ -0,0 +1,90 @@ +DROP TABLE IF EXISTS `playercreateinfo_spells`; + +DROP TABLE IF EXISTS `playercreateinfo_skills`; +CREATE TABLE `playercreateinfo_skills` ( + `raceMask` int(10) unsigned NOT NULL, + `classMask` int(10) unsigned NOT NULL, + `skill` smallint(5) unsigned NOT NULL, + `rank` smallint(5) unsigned NOT NULL DEFAULT '0', + `comment` varchar(255) DEFAULT NULL, + PRIMARY KEY (`raceMask`,`classMask`,`skill`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO `playercreateinfo_skills` VALUES +(0,0,95,0,'Defense'), +(0,0,162,0,'Unarmed'), +(0,0,183,0,'GENERIC (DND)'), +(0,0,415,0,'Cloth'), +(0,0,777,0,'Mounts'), +(0,0,778,0,'Companion Pets'), +(0,1,26,0,'Warrior - Arms'), +(0,1,256,0,'Warrior - Fury'), +(0,1,257,0,'Warrior - Protection'), +(0,2,184,0,'Paladin - Retribution'), +(0,2,267,0,'Paladin - Protection'), +(0,2,594,0,'Paladin - Holy'), +(0,4,50,0,'Hunter - Beast Mastery'), +(0,4,51,0,'Hunter - Survival'), +(0,4,163,0,'Hunter - Marksmanship'), +(0,8,38,0,'Rogue - Combat'), +(0,8,39,0,'Rogue - Subtlety'), +(0,8,176,0,'Thrown'), +(0,8,253,0,'Rogue - Assassination'), +(0,16,56,0,'Priest - Holy'), +(0,16,78,0,'Priest - Shadow'), +(0,16,613,0,'Priest - Discipline'), +(0,32,129,4,'Death Knight - First Aid'), +(0,32,229,0,'Polearms'), +(0,32,293,0,'Plate'), +(0,32,762,0,'Death Knight - Riding'), +(0,32,770,0,'Death Knight - Blood'), +(0,32,771,0,'Death Knight - Frost'), +(0,32,772,0,'Death Knight - Unholy'), +(0,35,55,0,'Two-Handed Swords'), +(0,35,413,0,'Mail'), +(0,37,44,0,'Axes'), +(0,37,172,0,'Two-Handed Axes'), +(0,39,43,0,'Swords'), +(0,40,118,0,'Dual Wield'), +(0,64,373,0,'Shaman - Enhancement'), +(0,64,374,0,'Shaman - Restoration'), +(0,64,375,0,'Shaman - Elemental'), +(0,67,433,0,'Shield'), +(0,128,6,0,'Mage - Frost'), +(0,128,8,0,'Mage - Fire'), +(0,128,237,0,'Mage - Arcane'), +(0,256,354,0,'Warlock - Demonology'), +(0,256,355,0,'Warlock - Affliction'), +(0,256,593,0,'Warlock - Destruction'), +(0,400,228,0,'Wands'), +(0,1024,134,0,'Druid - Feral'), +(0,1024,573,0,'Druid - Restoration'), +(0,1024,574,0,'Druid - Balance'), +(0,1107,54,0,'Maces'), +(0,1135,414,0,'Leather'), +(0,1488,136,0,'Staves'), +(1,0,754,0,'Human - Racial'), +(2,0,125,0,'Orc - Racial'), +(4,0,101,0,'Dwarf - Racial'), +(4,0,111,0,'Language: Dwarven'), +(8,0,126,0,'Night Elf - Racial'), +(8,0,137,0,'Language: Thalassian'), +(16,0,220,0,'Undead - Racial'), +(16,0,673,0,'Language: Forsaken'), +(32,0,113,0,'Language: Darnassian'), +(32,0,124,0,'Tauren - Racial'), +(36,4,46,0,'Guns'), +(64,0,313,0,'Language: Gnomish'), +(64,0,753,0,'Gnome - Racial'), +(128,0,315,0,'Language: Troll'), +(128,0,733,0,'Troll - Racial'), +(512,0,115,0,'Language: Taurahe'), +(512,0,756,0,'Blood Elf - Racial'), +(650,4,45,0,'Bows'), +(690,0,109,0,'Language: Orcish'), +(735,1293,173,0,'Daggers'), +(1024,0,759,0,'Language: Draenei'), +(1024,0,760,0,'Draenei - Racial'), +(1024,4,226,0,'Crossbows'), +(1061,3,160,0,'Two-Handed Maces'), +(1101,0,98,0,'Language: Common'); diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 10b7c25bb1f..03180b35cb5 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -326,8 +326,8 @@ enum MapFlags enum AbilytyLearnType { - ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1, - ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2 + SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE = 1, // Spell state will update depending on skill value + SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN = 2 // Spell will be learned/removed together with entire skill }; enum ItemEnchantmentType @@ -356,7 +356,7 @@ enum SkillRaceClassInfoFlags SKILL_FLAG_UNLEARNABLE = 0x20, // Skill can be unlearned SKILL_FLAG_INCLUDE_IN_SORT = 0x80, // Spells belonging to a skill with this flag will additionally compare skill ids when sorting spellbook in client SKILL_FLAG_NOT_TRAINABLE = 0x100, - SKILL_FLAG_MONO_VALUE = 0x400 // Skill always has value 1 + SKILL_FLAG_MONO_VALUE = 0x400 // Skill always has value 1 - clientside display flag, real value can be different }; enum SpellCategoryFlags diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 92d00b20645..e960422cbbc 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -450,7 +450,7 @@ void LoadDBCStores(const std::string& dataPath) if (spellInfo->spellLevel) continue; - if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) + if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; sPetFamilySpellsStore[i].insert(spellInfo->Id); diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 2da166fb049..946cbc42f25 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1535,23 +1535,6 @@ struct ScalingStatValuesEntry // uint32 displayOrder; // 19 m_sortIndex //}; -//struct SkillRaceClassInfoEntry{ -// uint32 id; // 0 m_ID -// uint32 skillId; // 1 m_skillID -// uint32 raceMask; // 2 m_raceMask -// uint32 classMask; // 3 m_classMask -// uint32 flags; // 4 m_flags -// uint32 reqLevel; // 5 m_minLevel -// uint32 skillTierId; // 6 m_skillTierID -// uint32 skillCostID; // 7 m_skillCostIndex -//}; - -//struct SkillTiersEntry{ -// uint32 id; // 0 m_ID -// uint32 skillValue[16]; // 1-17 m_cost -// uint32 maxSkillValue[16]; // 18-32 m_valueMax -//}; - struct SkillLineEntry { uint32 id; // 0 m_ID @@ -1578,7 +1561,7 @@ struct SkillLineAbilityEntry //uint32 classmaskNot; // 6 m_excludeClass uint32 req_skill_value; // 7 m_minSkillLineRank uint32 forward_spellid; // 8 m_supercededBySpell - uint32 learnOnGetSkill; // 9 m_acquireMethod + uint32 AutolearnType; // 9 m_acquireMethod uint32 max_value; // 10 m_trivialSkillLineRankHigh uint32 min_value; // 11 m_trivialSkillLineRankLow //uint32 characterPoints[2]; // 12-13 m_characterPoints[2] diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8653106a865..b32ef34edb2 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1134,7 +1134,8 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) } // original spells - learnDefaultSpells(); + LearnDefaultSkills(); + LearnCustomSpells(); // original action bar for (PlayerCreateInfoActions::const_iterator action_itr = info->action.begin(); action_itr != info->action.end(); ++action_itr) @@ -3827,34 +3828,14 @@ bool Player::addSpell(uint32 spellId, bool active, bool learning, bool dependent if (!pSkill) continue; - if (!Has310Flyer(false) && pSkill->id == SKILL_MOUNTS) + if (!HasSkill(pSkill->id)) + LearnDefaultSkill(pSkill->id, 0); + + if (pSkill->id == SKILL_MOUNTS && !Has310Flyer(false)) for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED && spellInfo->Effects[i].CalcValue() == 310) SetHas310Flyer(true); - - if (HasSkill(pSkill->id)) - continue; - - if (_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || - // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0)) - { - switch (GetSkillRangeType(pSkill, _spell_idx->second->racemask != 0)) - { - case SKILL_RANGE_LANGUAGE: - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 300, 300); - break; - case SKILL_RANGE_LEVEL: - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, GetMaxSkillValueForLevel()); - break; - case SKILL_RANGE_MONO: - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 1, 1); - break; - default: - break; - } - } } } @@ -4079,33 +4060,27 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) // not ranked skills SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spell_id); - for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) + // most likely will never be used, haven't heard of cases where players unlearn a mount + if (Has310Flyer(false) && spellInfo) { - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); - if (!pSkill) - continue; - - if ((_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL && - pSkill->categoryId != SKILL_CATEGORY_CLASS) ||// not unlearn class skills (spellbook/talent pages) - // lockpicking/runeforging special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - ((pSkill->id == SKILL_LOCKPICKING || pSkill->id == SKILL_RUNEFORGING) && _spell_idx->second->max_value == 0)) + for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) { - // not reset skills for professions and racial abilities - if ((pSkill->categoryId == SKILL_CATEGORY_SECONDARY || pSkill->categoryId == SKILL_CATEGORY_PROFESSION) && - (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask != 0)) + SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); + if (!pSkill) continue; - SetSkill(pSkill->id, GetSkillStep(pSkill->id), 0, 0); - } - - // most likely will never be used, haven't heard of cases where players unlearn a mount - if (Has310Flyer(false) && _spell_idx->second->skillId == SKILL_MOUNTS) - { - if (spellInfo) + if (_spell_idx->second->skillId == SKILL_MOUNTS) + { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED && spellInfo->Effects[i].CalcValue() == 310) + { Has310Flyer(true, spell_id); // with true as first argument its also used to set/remove the flag + break; + } + } + } } } } @@ -6080,9 +6055,6 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (!skill_id) return false; - if (skill_id == SKILL_FIST_WEAPONS) - skill_id = SKILL_UNARMED; - SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; @@ -6097,13 +6069,14 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (value < max) { - uint32 new_value = value+step; + uint32 new_value = value + step; if (new_value > max) new_value = max; SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max)); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; + UpdateSkillEnchantments(skill_id, value, new_value); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); return true; @@ -6277,9 +6250,25 @@ void Player::UpdateWeaponSkill(WeaponAttackType attType) Item* tmpitem = GetWeaponForAttack(attType, true); if (!tmpitem && attType == BASE_ATTACK) + { + // Keep unarmed & fist weapon skills in sync UpdateSkill(SKILL_UNARMED, weapon_skill_gain); + UpdateSkill(SKILL_FIST_WEAPONS, weapon_skill_gain); + } else if (tmpitem && tmpitem->GetTemplate()->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE) - UpdateSkill(tmpitem->GetSkill(), weapon_skill_gain); + { + switch (tmpitem->GetTemplate()->SubClass) + { + case ITEM_SUBCLASS_WEAPON_FISHING_POLE: + break; + case ITEM_SUBCLASS_WEAPON_FIST: + UpdateSkill(SKILL_UNARMED, weapon_skill_gain); + // no break intended + default: + UpdateSkill(tmpitem->GetSkill(), weapon_skill_gain); + break; + } + } UpdateAllCritPercentages(); } @@ -6352,11 +6341,11 @@ void Player::UpdateSkillsForLevel() continue; uint32 pskill = itr->first; - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(pskill); - if (!pSkill) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass()); + if (!rcEntry) continue; - if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL) + if (GetSkillRangeType(rcEntry) != SKILL_RANGE_LEVEL) continue; uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); @@ -17704,7 +17693,8 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // after spell and quest load InitTalentForLevel(); - learnDefaultSpells(); + LearnDefaultSkills(); + LearnCustomSpells(); // must be before inventory (some items required reputation check) m_reputationMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_REPUTATION)); @@ -23078,15 +23068,19 @@ void Player::resetSpells(bool myClassOnly) for (PlayerSpellMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter) removeSpell(iter->first, false, false); // only iter->first can be accessed, object by iter->second can be deleted already - learnDefaultSpells(); + LearnDefaultSkills(); + LearnCustomSpells(); learnQuestRewardedSpells(); } -void Player::learnDefaultSpells() +void Player::LearnCustomSpells() { + if (!sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS)) + return; + // learn default race/class spells PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); - for (PlayerCreateInfoSpells::const_iterator itr = info->spell.begin(); itr != info->spell.end(); ++itr) + for (PlayerCreateInfoSpells::const_iterator itr = info->customSpells.begin(); itr != info->customSpells.end(); ++itr) { uint32 tspell = *itr; TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial spell, id = %u", uint32(getClass()), uint32(getRace()), tspell); @@ -23097,6 +23091,63 @@ void Player::learnDefaultSpells() } } +void Player::LearnDefaultSkills() +{ + // learn default race/class skills + PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); + for (PlayerCreateInfoSkills::const_iterator itr = info->skills.begin(); itr != info->skills.end(); ++itr) + { + uint32 skillId = itr->SkillId; + if (HasSkill(skillId)) + continue; + + LearnDefaultSkill(skillId, itr->Rank); + } +} + +void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) +{ + SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(skillId, getRace(), getClass()); + if (!rcInfo) + return; + + TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial skill, id = %u", uint32(getClass()), uint32(getRace()), skillId); + switch (GetSkillRangeType(rcInfo)) + { + case SKILL_RANGE_LANGUAGE: + SetSkill(skillId, 0, 300, 300); + break; + case SKILL_RANGE_LEVEL: + { + uint16 skillValue = 0; + uint16 maxValue = GetMaxSkillValueForLevel(); + if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + skillValue = maxValue; + else + skillValue = std::min(std::max({ 1, uint16((getLevel() - 1) * 5) }), maxValue); + + SetSkill(skillId, 0, skillValue, maxValue); + break; + } + case SKILL_RANGE_MONO: + SetSkill(skillId, 0, 1, 1); + break; + case SKILL_RANGE_RANK: + { + if (!rank) + break; + + SkillTiersEntry const* tier = sSkillTiersStore.LookupEntry(rcInfo->SkillTier); + uint16 maxValue = std::max(GetMaxSkillValue(skillId), tier->MaxSkill[std::max(rank - 1, 0)]); + uint16 skillValue = std::min(std::max({ uint16(1), uint16((getLevel() - 1) * 5) }), maxValue); + SetSkill(skillId, rank, skillValue, maxValue); + break; + } + default: + break; + } +} + void Player::learnQuestRewardedSpells(Quest const* quest) { int32 spell_id = quest->GetRewSpellCast(); @@ -23194,29 +23245,35 @@ void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value) { uint32 raceMask = getRaceMask(); uint32 classMask = getClassMask(); - for (uint32 j=0; jskillId != skill_id || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + if (!pAbility || pAbility->skillId != skill_id) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pAbility->spellId); + if (!spellInfo) + continue; + + if (pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; + // Check race if set if (pAbility->racemask && !(pAbility->racemask & raceMask)) continue; + // Check class if set if (pAbility->classmask && !(pAbility->classmask & classMask)) continue; - if (sSpellMgr->GetSpellInfo(pAbility->spellId)) - { - // need unlearn spell - if (skill_value < pAbility->req_skill_value) - removeSpell(pAbility->spellId); - // need learn - else if (!IsInWorld()) - addSpell(pAbility->spellId, true, true, true, false); - else - learnSpell(pAbility->spellId, true); - } + // need unlearn spell + if (skill_value < pAbility->req_skill_value && pAbility->AutolearnType == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) + removeSpell(pAbility->spellId); + // need learn + else if (!IsInWorld()) + addSpell(pAbility->spellId, true, true, true, false); + else + learnSpell(pAbility->spellId, true); } } @@ -23944,7 +24001,7 @@ bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const return pOther->GetDistance(player) <= sWorld->getFloatConfig(CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE); } -uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const +uint32 Player::GetBaseWeaponSkillValue(WeaponAttackType attType) const { Item* item = GetWeaponForAttack(attType, true); @@ -23952,8 +24009,8 @@ uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const if (attType != BASE_ATTACK && !item) return 0; - // weapon skill or (unarmed for base attack and for fist weapons) - uint32 skill = (item && item->GetSkill() != SKILL_FIST_WEAPONS) ? item->GetSkill() : uint32(SKILL_UNARMED); + // weapon skill or (unarmed for base attack) + uint32 skill = item ? item->GetSkill() : uint32(SKILL_UNARMED); return GetBaseSkillValue(skill); } @@ -24907,15 +24964,15 @@ void Player::_LoadSkills(PreparedQueryResult result) uint16 value = fields[1].GetUInt16(); uint16 max = fields[2].GetUInt16(); - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(skill); - if (!pSkill) + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skill, getRace(), getClass()); + if (!rcEntry) { TC_LOG_ERROR("entities.player", "Character %u has skill %u that does not exist.", GetGUIDLow(), skill); continue; } // set fixed skill ranges - switch (GetSkillRangeType(pSkill, false)) + switch (GetSkillRangeType(rcEntry)) { case SKILL_RANGE_LANGUAGE: // 300..300 value = max = 300; @@ -24923,9 +24980,12 @@ void Player::_LoadSkills(PreparedQueryResult result) case SKILL_RANGE_MONO: // 1..1, grey monolite bar value = max = 1; break; + case SKILL_RANGE_LEVEL: + max = GetMaxSkillValueForLevel(); default: break; } + if (value == 0) { TC_LOG_ERROR("entities.player", "Character %u has skill %u with value 0. Will be deleted.", GetGUIDLow(), skill); @@ -24940,11 +25000,20 @@ void Player::_LoadSkills(PreparedQueryResult result) continue; } - // enable unlearn button for primary professions only - if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) - SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 1)); - else - SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 0)); + uint16 skillStep = 0; + if (SkillTiersEntry const* skillTier = sSkillTiersStore.LookupEntry(rcEntry->SkillTier)) + { + for (uint32 i = 0; i < MAX_SKILL_STEP; ++i) + { + if (skillTier->MaxSkill[skillStep] == max) + { + skillStep = i + 1; + break; + } + } + } + + SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, skillStep)); SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), MAKE_SKILL_VALUE(value, max)); SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); @@ -24970,34 +25039,6 @@ void Player::_LoadSkills(PreparedQueryResult result) SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0); SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); } - - // special settings - if (getClass() == CLASS_DEATH_KNIGHT) - { - uint8 base_level = std::min(getLevel(), uint8(sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL))); - if (base_level < 1) - base_level = 1; - uint16 base_skill = (base_level-1)*5; // 270 at starting level 55 - if (base_skill < 1) - base_skill = 1; // skill mast be known and then > 0 in any case - - if (GetPureSkillValue(SKILL_FIRST_AID) < base_skill) - SetSkill(SKILL_FIRST_AID, 4 /*artisan*/, base_skill, 300); - if (GetPureSkillValue(SKILL_AXES) < base_skill) - SetSkill(SKILL_AXES, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_DEFENSE) < base_skill) - SetSkill(SKILL_DEFENSE, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_POLEARMS) < base_skill) - SetSkill(SKILL_POLEARMS, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_SWORDS) < base_skill) - SetSkill(SKILL_SWORDS, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_2H_AXES) < base_skill) - SetSkill(SKILL_2H_AXES, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_2H_SWORDS) < base_skill) - SetSkill(SKILL_2H_SWORDS, 0, base_skill, base_skill); - if (GetPureSkillValue(SKILL_UNARMED) < base_skill) - SetSkill(SKILL_UNARMED, 0, base_skill, base_skill); - } } uint32 Player::GetPhaseMaskForSpawn() const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index fdebbde0ae2..5f500b7f1d8 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -249,6 +249,14 @@ struct PlayerCreateInfoAction typedef std::list PlayerCreateInfoActions; +struct PlayerCreateInfoSkill +{ + uint16 SkillId; + uint16 Rank; +}; + +typedef std::list PlayerCreateInfoSkills; + struct PlayerInfo { // existence checked by displayId != 0 @@ -263,8 +271,9 @@ struct PlayerInfo uint16 displayId_m; uint16 displayId_f; PlayerCreateInfoItems item; - PlayerCreateInfoSpells spell; + PlayerCreateInfoSpells customSpells; PlayerCreateInfoActions action; + PlayerCreateInfoSkills skills; PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1 }; @@ -1573,7 +1582,9 @@ class Player : public Unit, public GridObject void learnSpell(uint32 spell_id, bool dependent); void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true); void resetSpells(bool myClassOnly = false); - void learnDefaultSpells(); + void LearnCustomSpells(); + void LearnDefaultSkills(); + void LearnDefaultSkill(uint32 skillId, uint16 rank); void learnQuestRewardedSpells(); void learnQuestRewardedSpells(Quest const* quest); void learnSpellHighRank(uint32 spellid); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5eb48160e8a..154688b2cfc 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2834,12 +2834,10 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) if (IsInFeralForm()) return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact - // weapon skill or (unarmed for base attack and fist weapons) - uint32 skill; - if (item && item->GetSkill() != SKILL_FIST_WEAPONS) + // weapon skill or (unarmed for base attack) + uint32 skill = SKILL_UNARMED; + if (item) skill = item->GetSkill(); - else - skill = SKILL_UNARMED; // in PvP use full skill instead current skill value value = (target && target->IsControlledByPlayer()) @@ -15288,7 +15286,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) group->SendLooter(creature, NULL); // Update round robin looter only if the creature had loot - if (!creature->loot.empty()) + if (!loot->empty()) group->UpdateLooterGuid(creature); } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9eb7d5ec1bf..278460e73dd 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3322,17 +3322,91 @@ void ObjectMgr::LoadPlayerInfo() } } + + // Load playercreate skills + TC_LOG_INFO("server.loading", "Loading Player Create Skill Data..."); + { + uint32 oldMSTime = getMSTime(); + + QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, skill, rank FROM playercreateinfo_skills"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty."); + } + else + { + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + uint32 raceMask = fields[0].GetUInt32(); + uint32 classMask = fields[1].GetUInt32(); + PlayerCreateInfoSkill skill; + skill.SkillId = fields[2].GetUInt16(); + skill.Rank = fields[3].GetUInt16(); + + if (skill.Rank >= MAX_SKILL_STEP) + { + TC_LOG_ERROR("sql.sql", "Skill rank value %hu set for skill %hu raceMask %u classMask %u is too high, max allowed value is %d", skill.Rank, skill.SkillId, raceMask, classMask, MAX_SKILL_STEP); + continue; + } + + if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE)) + { + TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_skills` table, ignoring.", raceMask); + continue; + } + + if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE)) + { + TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_skills` table, ignoring.", classMask); + continue; + } + + if (!sSkillLineStore.LookupEntry(skill.SkillId)) + { + TC_LOG_ERROR("sql.sql", "Wrong skill id %u in `playercreateinfo_skills` table, ignoring.", skill.SkillId); + continue; + } + + for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex) + { + if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask)) + { + for (uint32 classIndex = CLASS_WARRIOR; classIndex < MAX_CLASSES; ++classIndex) + { + if (classMask == 0 || ((1 << (classIndex - 1)) & classMask)) + { + if (!GetSkillRaceClassInfo(skill.SkillId, raceIndex, classIndex)) + continue; + + if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) + { + info->skills.push_back(skill); + ++count; + } + } + } + } + } + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u player create skills in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + } + } + // Load playercreate spells TC_LOG_INFO("server.loading", "Loading Player Create Spell Data..."); { uint32 oldMSTime = getMSTime(); - std::string tableName = sWorld->getBoolConfig(CONFIG_START_ALL_SPELLS) ? "playercreateinfo_spell_custom" : "playercreateinfo_spell"; - QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM %s", tableName.c_str()); + QueryResult result = WorldDatabase.PQuery("SELECT racemask, classmask, Spell FROM playercreateinfo_spell_custom"); if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `%s` is empty.", tableName.c_str()); + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell_custom` is empty."); } else { @@ -3347,13 +3421,13 @@ void ObjectMgr::LoadPlayerInfo() if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `%s` table, ignoring.", raceMask, tableName.c_str()); + TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_spell_custom` table, ignoring.", raceMask); continue; } if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `%s` table, ignoring.", classMask, tableName.c_str()); + TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_spell_custom` table, ignoring.", classMask); continue; } @@ -3367,7 +3441,7 @@ void ObjectMgr::LoadPlayerInfo() { if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) { - info->spell.push_back(spellId); + info->customSpells.push_back(spellId); ++count; } // We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them. @@ -3381,7 +3455,7 @@ void ObjectMgr::LoadPlayerInfo() } while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u custom player create spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } @@ -7808,36 +7882,27 @@ int32 ObjectMgr::GetBaseReputationOf(FactionEntry const* factionEntry, uint8 rac return 0; } -SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial) +SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry) { - switch (pSkill->categoryId) + SkillLineEntry const* skill = sSkillLineStore.LookupEntry(rcEntry->SkillId); + if (!skill) + return SKILL_RANGE_NONE; + + if (sSkillTiersStore.LookupEntry(rcEntry->SkillTier)) + return SKILL_RANGE_RANK; + + if (rcEntry->SkillId == SKILL_RUNEFORGING) + return SKILL_RANGE_MONO; + + switch (skill->categoryId) { - case SKILL_CATEGORY_LANGUAGES: return SKILL_RANGE_LANGUAGE; - case SKILL_CATEGORY_WEAPON: - if (pSkill->id != SKILL_FIST_WEAPONS) - return SKILL_RANGE_LEVEL; - else - return SKILL_RANGE_MONO; case SKILL_CATEGORY_ARMOR: - case SKILL_CATEGORY_CLASS: - if (pSkill->id != SKILL_LOCKPICKING) - return SKILL_RANGE_MONO; - else - return SKILL_RANGE_LEVEL; - case SKILL_CATEGORY_SECONDARY: - case SKILL_CATEGORY_PROFESSION: - // not set skills for professions and racial abilities - if (IsProfessionSkill(pSkill->id)) - return SKILL_RANGE_RANK; - else if (racial) - return SKILL_RANGE_NONE; - else - return SKILL_RANGE_MONO; - default: - case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc - case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) - return SKILL_RANGE_NONE; + return SKILL_RANGE_MONO; + case SKILL_CATEGORY_LANGUAGES: + return SKILL_RANGE_LANGUAGE; } + + return SKILL_RANGE_LEVEL; } void ObjectMgr::LoadGameTele() diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index e5e55b847d3..3f8013bbd78 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -643,7 +643,7 @@ enum SkillRangeType SKILL_RANGE_NONE // 0..0 always }; -SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial); +SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry); #define MAX_PLAYER_NAME 12 // max allowed by client name length #define MAX_INTERNAL_PLAYER_NAME 15 // max server internal player name length (> MAX_PLAYER_NAME for support declined names) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 4d97dc97e5b..8034002a470 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -967,7 +967,7 @@ bool SpellInfo::IsAbilityLearnedWithProfession() const for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) { SkillLineAbilityEntry const* pAbility = _spell_idx->second; - if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + if (!pAbility || pAbility->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) continue; if (pAbility->req_skill_value > 0) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 6f56c0ebc40..77450dc859a 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2382,7 +2382,7 @@ void SpellMgr::LoadPetLevelupSpellMap() if (skillLine->skillId != creatureFamily->skillLine[j]) continue; - if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) + if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; SpellInfo const* spell = GetSpellInfo(skillLine->spellId); diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 12721c61936..03d10149ae5 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -332,7 +332,8 @@ public: if (!handler->extractPlayerTarget((char*)args, &target)) return false; - target->learnDefaultSpells(); + target->LearnDefaultSkills(); + target->LearnCustomSpells(); target->learnQuestRewardedSpells(); handler->PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST, handler->GetNameLink(target).c_str()); -- cgit v1.2.3