TrinityCore
Loading...
Searching...
No Matches
boss_icecrown_gunship_battle.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "icecrown_citadel.h"
19#include "CellImpl.h"
20#include "Containers.h"
21#include "CreatureTextMgr.h"
22#include "GridNotifiersImpl.h"
23#include "InstanceScript.h"
24#include "Map.h"
25#include "MotionMaster.h"
26#include "MovementPackets.h"
27#include "MoveSplineInit.h"
28#include "ObjectAccessor.h"
29#include "PassiveAI.h"
30#include "ScriptedCreature.h"
31#include "ScriptedGossip.h"
32#include "ScriptMgr.h"
33#include "SpellAuraEffects.h"
34#include "SpellHistory.h"
35#include "SpellMgr.h"
36#include "SpellScript.h"
37#include "TemporarySummon.h"
38#include "Transport.h"
39#include "Vehicle.h"
40#include <G3D/Vector3.h>
41
82
115
117{
118 // Applied on friendly transport NPCs
127
128 // Murading Bronzebeard
129 // High Overlord Saurfang
134
135 // Applied on enemy NPCs
138
139 // Gunship Hull
142
143 // Hostile NPCs
148 SPELL_ELITE = 71195,
150
151 // Skybreaker Sorcerer
152 // Kor'kron Battle-Mage
155
156 // Skybreaker Rifleman
157 // Kor'kron Axethrower
158 SPELL_SHOOT = 70162,
163
164 // Skybreaker Mortar Soldier
165 // Kor'kron Rocketeer
170
171 // Skybreaker Marine
172 // Kor'kron Reaver
174
175 // Skybreaker Sergeant
176 // Kor'kron Sergeant
179
180 //
184
185 // Rocket Pack
189
190 // Alliance Gunship Cannon
191 // Horde Gunship Cannon
196
207
216
217Position const SkybreakerAddsSpawnPos = { 15.91131f, 0.0f, 20.4628f, float(M_PI) };
218Position const OrgrimsHammerAddsSpawnPos = { 60.728395f, 0.0f, 38.93467f, float(M_PI) };
219
220// Horde encounter
221Position const SkybreakerTeleportPortal = { 6.666975f, 0.013001f, 20.87888f, 0.0f };
222Position const OrgrimsHammerTeleportExit = { 7.461699f, 0.158853f, 35.72989f, 0.0f };
223
224// Alliance encounter
225Position const OrgrimsHammerTeleportPortal = { 47.550990f, -0.101778f, 37.61111f, 0.0f };
226Position const SkybreakerTeleportExit = { -17.55738f, -0.090421f, 21.18366f, 0.0f };
227
228G3D::Vector3 const MuradinExitPath[] =
229{
230 { 8.130936f, -0.2699585f, 20.31728f },
231 { 6.380936f, -0.2699585f, 20.31728f },
232 { 3.507703f, 0.02986573f, 20.78463f },
233 { -2.767633f, 3.743143f, 20.37663f },
234 { -4.017633f, 4.493143f, 20.12663f },
235 { -7.242224f, 6.856013f, 20.03468f },
236 { -7.742224f, 8.606013f, 20.78468f },
237 { -7.992224f, 9.856013f, 21.28468f },
238 { -12.24222f, 23.10601f, 21.28468f },
239 { -14.88477f, 25.20844f, 21.59985f },
240};
241
242G3D::Vector3 const SaurfangExitPath[] =
243{
244 { 30.43987f, 0.1475817f, 36.10674f },
245 { 21.36141f, -3.056458f, 35.42970f },
246 { 19.11141f, -3.806458f, 35.42970f },
247 { 19.01736f, -3.299440f, 35.39428f },
248 { 18.6747f, -5.862823f, 35.66611f },
249 { 18.6747f, -7.862823f, 35.66611f },
250 { 18.1747f, -17.36282f, 35.66611f },
251 { 18.1747f, -22.61282f, 35.66611f },
252 { 17.9247f, -24.36282f, 35.41611f },
253 { 17.9247f, -26.61282f, 35.66611f },
254 { 17.9247f, -27.86282f, 35.66611f },
255 { 17.9247f, -29.36282f, 35.66611f },
256 { 15.33203f, -30.42621f, 35.93796f }
257};
258
260{
261 // Freezing the cannons
263
264 // Channeling the portal, refilled with adds that board player's ship
267
268 // Rifleman
273
274 // Additional Rifleman on 25 man
279
280 // Mortar
283
284 // Additional spawns on 25 man
287
288 // Marines
291
292 // Additional spawns on 25 man
295
296 // Sergeants
298
299 // Additional spawns on 25 man
301
304
311
313{
314 { NPC_SKYBREAKER_SORCERER, { -9.479858f, 0.05663967f, 20.77026f, 4.729842f }, 0 },
315
316 { NPC_SKYBREAKER_SORCERER, { 6.385986f, 4.978760f, 20.55417f, 4.694936f }, 0 },
317 { NPC_SKYBREAKER_SORCERER, { 6.579102f, -4.674561f, 20.55060f, 1.553343f }, 0 },
318
319 { NPC_SKYBREAKER_RIFLEMAN, { -29.563900f, -17.95801f, 20.73837f, 4.747295f }, 30 },
320 { NPC_SKYBREAKER_RIFLEMAN, { -18.017210f, -18.82056f, 20.79150f, 4.747295f }, 30 },
321 { NPC_SKYBREAKER_RIFLEMAN, { -9.1193850f, -18.79102f, 20.58887f, 4.712389f }, 30 },
322 { NPC_SKYBREAKER_RIFLEMAN, { -0.3364258f, -18.87183f, 20.56824f, 4.712389f }, 30 },
323
324 { NPC_SKYBREAKER_RIFLEMAN, { -34.705810f, -17.67261f, 20.51523f, 4.729842f }, 30 },
325 { NPC_SKYBREAKER_RIFLEMAN, { -23.562010f, -18.28564f, 20.67859f, 4.729842f }, 30 },
326 { NPC_SKYBREAKER_RIFLEMAN, { -13.602780f, -18.74268f, 20.59622f, 4.712389f }, 30 },
327 { NPC_SKYBREAKER_RIFLEMAN, { -4.3350220f, -18.84619f, 20.58234f, 4.712389f }, 30 },
328
329 { NPC_SKYBREAKER_MORTAR_SOLDIER, { -31.70142f, 18.02783f, 20.77197f, 4.712389f }, 30 },
330 { NPC_SKYBREAKER_MORTAR_SOLDIER, { -9.368652f, 18.75806f, 20.65335f, 4.712389f }, 30 },
331
332 { NPC_SKYBREAKER_MORTAR_SOLDIER, { -20.40851f, 18.40381f, 20.50647f, 4.694936f }, 30 },
333 { NPC_SKYBREAKER_MORTAR_SOLDIER, { 0.1585693f, 18.11523f, 20.41949f, 4.729842f }, 30 },
334
337
340
342
344};
345
347{
348 { NPC_KOR_KRON_BATTLE_MAGE, { 13.58548f, 0.3867192f, 34.99243f, 1.53589f }, 0 },
349
350 { NPC_KOR_KRON_BATTLE_MAGE, { 47.29290f, -4.308941f, 37.55550f, 1.570796f }, 0 },
351 { NPC_KOR_KRON_BATTLE_MAGE, { 47.34621f, 4.032004f, 37.70952f, 4.817109f }, 0 },
352
353 { NPC_KOR_KRON_AXETHROWER, { -12.09280f, 27.65942f, 33.58557f, 1.53589f }, 30 },
354 { NPC_KOR_KRON_AXETHROWER, { -3.170555f, 28.30652f, 34.21082f, 1.53589f }, 30 },
355 { NPC_KOR_KRON_AXETHROWER, { 14.928040f, 26.18018f, 35.47803f, 1.53589f }, 30 },
356 { NPC_KOR_KRON_AXETHROWER, { 24.703310f, 25.36584f, 35.97845f, 1.53589f }, 30 },
357
358 { NPC_KOR_KRON_AXETHROWER, { -16.65302f, 27.59668f, 33.18726f, 1.53589f }, 30 },
359 { NPC_KOR_KRON_AXETHROWER, { -8.084572f, 28.21448f, 33.93805f, 1.53589f }, 30 },
360 { NPC_KOR_KRON_AXETHROWER, { 7.594765f, 27.41968f, 35.00775f, 1.53589f }, 30 },
361 { NPC_KOR_KRON_AXETHROWER, { 20.763390f, 25.58215f, 35.75287f, 1.53589f }, 30 },
362
363 { NPC_KOR_KRON_ROCKETEER, { -11.44849f, -25.71838f, 33.64343f, 1.518436f }, 30 },
364 { NPC_KOR_KRON_ROCKETEER, { 12.30336f, -25.69653f, 35.32373f, 1.518436f }, 30 },
365
366 { NPC_KOR_KRON_ROCKETEER, { -0.05931854f, -25.46399f, 34.50592f, 1.518436f }, 30 },
367 { NPC_KOR_KRON_ROCKETEER, { 27.62149000f, -23.48108f, 36.12708f, 1.518436f }, 30 },
368
371
374
376
378};
379
381{
382public:
387
388 void SetTransport(Transport* transport) { _transport = transport; }
389
391 {
392 _transport = nullptr;
393 for (uint32 i = 0; i < MAX_SLOTS; ++i)
394 _controlledSlots[i].Clear();
395
396 memset(_respawnCooldowns, 0, sizeof(time_t)* MAX_SLOTS);
399 }
400
402 {
403 if (!_transport)
404 return false;
405
406 bool summoned = false;
407 time_t now = GameTime::GetGameTime();
408 for (int32 i = first; i <= last; ++i)
409 {
410 if (_respawnCooldowns[i] > now)
411 continue;
412
413 if (!_controlledSlots[i].IsEmpty())
414 {
416 if (current && current->IsAlive())
417 continue;
418 }
419
421 {
422 _controlledSlots[i] = passenger->GetGUID();
423 _respawnCooldowns[i] = time_t(0);
424 passenger->AI()->SetData(ACTION_SET_SLOT, i);
425 summoned = true;
426 }
427 }
428
429 return summoned;
430 }
431
437
439 {
440 for (int32 i = first; i <= last; ++i)
441 if (!_controlledSlots[i])
442 return true;
443
444 return false;
445 }
446
447private:
449 {
450 Position newPos;
451 float angle = frand(float(-M_PI) * 0.5f, float(M_PI) * 0.5f);
452 newPos.m_positionX = _spawnPoint->GetPositionX() + 2.0f * std::cos(angle);
453 newPos.m_positionY = _spawnPoint->GetPositionY() + 2.0f * std::sin(angle);
456 return newPos;
457 }
458
464};
465
467{
468public:
469 DelayedMovementEvent(Creature* owner, Position const& dest) : _owner(owner), _dest(dest) { }
470
471 bool Execute(uint64, uint32) override
472 {
473 if (!_owner->IsAlive())
474 return true;
475
476 std::function<void(Movement::MoveSplineInit&)> initializer = [dest = _dest](Movement::MoveSplineInit& init)
477 {
478 init.DisableTransportPathTransformations();
479 init.MoveTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false);
480 };
482
483 return true;
484 }
485
486private:
489};
490
492{
493public:
494 ResetEncounterEvent(Unit* caster, uint32 spellId, ObjectGuid transport, ObjectGuid otherTransport) : _caster(caster), _spellId(spellId),
495 _transport(transport), _otherTransport(otherTransport) { }
496
497 bool Execute(uint64, uint32) override
498 {
500
502 go->AddObjectToRemoveList();
503
505 go->AddObjectToRemoveList();
506
507 return true;
508 }
509
510private:
515};
516
518{
519public:
520 static uint32 const ExperiencedSpells[5];
521 static Milliseconds const ExperiencedTimes[5];
522
523 BattleExperienceEvent(Creature* creature) : _creature(creature), _level(0) { }
524
525 bool Execute(uint64 timer, uint32 /*diff*/) override
526 {
527 if (!_creature->IsAlive())
528 return true;
529
531 ++_level;
532
534 if (_level < (_creature->GetMap()->IsHeroic() ? 4 : 3))
535 {
537 return false;
538 }
539
540 return true;
541 }
542
543private:
546};
547
549Milliseconds const BattleExperienceEvent::ExperiencedTimes[5] = { 100s, 70s, 60s, 90s, 0s };
550
552{
553 gunship_npc_AI(Creature* creature) : ScriptedAI(creature),
554 Instance(creature->GetInstanceScript()), Slot(nullptr), Index(uint32(-1))
555 {
557 me->SetRegenerateHealth(false);
558 }
559
560 void SetData(uint32 type, uint32 data) override
561 {
562 if (type == ACTION_SET_SLOT && data < MAX_SLOTS)
563 {
564 SetSlotInfo(data);
565
567
570
571 std::function<void(Movement::MoveSplineInit&)> initializer = [pos = Slot->TargetPosition](Movement::MoveSplineInit& init)
572 {
573 init.DisableTransportPathTransformations();
574 init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), false);
575 };
577 }
578 }
579
580 void EnterEvadeMode(EvadeReason /*why*/) override
581 {
582 if (!me->IsAlive() || !me->IsInCombat())
583 return;
584
585 me->CombatStop(true);
588 }
589
590 void JustDied(Unit* /*killer*/) override
591 {
592 if (Slot)
594 captain->AI()->SetData(ACTION_CLEAR_SLOT, Index);
595 }
596
610
611 bool CanAIAttack(Unit const* target) const override
612 {
614 return false;
616 }
617
618protected:
624
626 {
628 {
630 return false;
631 }
632
634 {
635 if (Unit* victim = me->SelectVictim())
636 if (!me->HasSpellFocus() && victim != me->GetVictim())
637 AttackStart(victim);
638
639 return me->GetVictim() != nullptr;
640 }
642 {
644 return false;
645 }
646
647 return true;
648 }
649
660
665};
666
667// 37215 - Orgrim's Hammer
668// 37540 - The Skybreaker
670{
671 public:
672 npc_gunship() : CreatureScript("npc_gunship") { }
673
675 {
676 npc_gunshipAI(Creature* creature) : NullCreatureAI(creature),
677 _teamInInstance(creature->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE)),
678 _summonedFirstMage(false), _died(false)
679 {
680 me->SetRegenerateHealth(false);
681 }
682
683 void DamageTaken(Unit* /*source*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
684 {
685 if (damage >= me->GetHealth())
686 {
687 JustDied(nullptr);
688 damage = me->GetHealth() - 1;
689 return;
690 }
691
693 return;
694
696 return;
697
698 if (!me->HealthBelowPctDamaged(90, damage))
699 return;
700
701 _summonedFirstMage = true;
703 captain->AI()->DoAction(ACTION_SPAWN_MAGE);
704 }
705
706 void JustDied(Unit* /*killer*/) override
707 {
708 if (_died)
709 return;
710
711 _died = true;
712
713 InstanceScript* instance = me->GetInstanceScript();
714 bool isVictory = me->GetTransport()->GetTransportGUID() == instance->GetGuidData(DATA_ENEMY_GUNSHIP);
715 instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, isVictory ? DONE : FAIL);
717 {
718 instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, creature);
719 creature->RemoveAurasDueToSpell(SPELL_CHECK_FOR_PLAYERS);
720 }
721
724
726 std::list<Creature*> creatures;
728 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
729 {
730 Creature* stalker = *itr;
731 stalker->RemoveAllAuras();
732 stalker->CombatStop(true);
733 }
734
735 uint32 explosionSpell = isVictory ? SPELL_EXPLOSION_VICTORY : SPELL_EXPLOSION_WIPE;
736 creatures.clear();
738 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
739 {
740 Creature* hull = *itr;
741 if (hull->GetTransport() != me->GetTransport())
742 continue;
743
744 hull->CastSpell(hull, explosionSpell, TRIGGERED_FULL_MASK);
745 }
746
747 creatures.clear();
749 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
750 {
751 Creature* cannon = *itr;
752 if (isVictory)
753 {
755 cannon->RemoveVehicleKit();
756 }
757 else
759 }
760
761 uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD;
762 uint8 textId = isVictory ? SAY_MURADIN_VICTORY : SAY_MURADIN_WIPE;
763 if (_teamInInstance == HORDE)
764 {
765 creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG;
766 textId = isVictory ? SAY_SAURFANG_VICTORY : SAY_SAURFANG_WIPE;
767 }
768
769 if (Creature* creature = me->FindNearestCreature(creatureEntry, 100.0f))
770 creature->AI()->Talk(textId);
771
772 if (isVictory)
773 {
775 otherTransport->EnableMovement(true);
776
777 if (Transport* transport = dynamic_cast<Transport*>(me->GetTransport()))
778 transport->EnableMovement(true);
779
781 {
783 ship->CastSpell(ship, SPELL_ACHIEVEMENT, TRIGGERED_FULL_MASK);
785 }
786
787 creatures.clear();
792 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
793 (*itr)->DespawnOrUnsummon(1ms);
794 }
795 else
796 {
799 instance->GetGuidData(DATA_ENEMY_GUNSHIP)), 8s);
800 }
801 }
802
803 void SetGUID(ObjectGuid const& guid, int32 id) override
804 {
805 if (id != ACTION_SHIP_VISITS)
806 return;
807
808 std::map<ObjectGuid, uint32>::iterator itr = _shipVisits.find(guid);
809 if (itr == _shipVisits.end())
810 _shipVisits[guid] = 1;
811 else
812 ++itr->second;
813 }
814
815 uint32 GetData(uint32 id) const override
816 {
817 if (id != ACTION_SHIP_VISITS)
818 return 0;
819
820 uint32 max = 0;
821 for (std::map<ObjectGuid, uint32>::const_iterator itr = _shipVisits.begin(); itr != _shipVisits.end(); ++itr)
822 max = std::max(max, itr->second);
823
824 return max;
825 }
826
827 private:
829 std::map<ObjectGuid, uint32> _shipVisits;
831 bool _died;
832 };
833
834 CreatureAI* GetAI(Creature* creature) const override
835 {
836 if (!creature->GetTransport())
837 return nullptr;
838
839 return GetIcecrownCitadelAI<npc_gunshipAI>(creature);
840 }
841};
842
843// 36939 - High Overlord Saurfang
845{
847 _instance(creature->GetInstanceScript())
848 {
850 _controller.SetTransport(dynamic_cast<Transport*>(creature->GetTransport()));
851 me->SetRegenerateHealth(false);
852 me->m_CombatDistance = 70.0f;
854 _axethrowersYellCooldown = time_t(0);
855 _rocketeersYellCooldown = time_t(0);
856 }
857
858 void InitializeAI() override
859 {
861
862 _events.Reset();
864 _axethrowersYellCooldown = time_t(0);
865 _rocketeersYellCooldown = time_t(0);
866 }
867
875
876 void EnterEvadeMode(EvadeReason /*why*/) override
877 {
878 if (!me->IsAlive())
879 return;
880
881 me->CombatStop(true);
884
885 Reset();
886 }
887
888 void DoAction(int32 action) override
889 {
890 if (action == ACTION_ENEMY_GUNSHIP_TALK)
891 {
893 muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS);
894
899
901 // Combat starts now
902 if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f))
904
905 if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f))
906 {
908 orgrimsHammer->CastSpell(orgrimsHammer, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK);
909 }
910
912 }
913 else if (action == ACTION_SPAWN_MAGE)
914 {
915 TimePoint now = GameTime::Now();
916 if (_firstMageCooldown > now)
917 _events.ScheduleEvent(EVENT_SUMMON_MAGE, std::chrono::duration_cast<Milliseconds>(_firstMageCooldown - now));
918 else
920 }
921 else if (action == ACTION_SPAWN_ALL_ADDS)
922 {
926 if (Is25ManRaid())
928 else
929 {
933 }
934 }
935 else if (action == ACTION_EXIT_SHIP)
936 {
937 std::function<void(Movement::MoveSplineInit&)> initializer = [](Movement::MoveSplineInit& init)
938 {
939 init.DisableTransportPathTransformations();
940 init.MovebyPath(SaurfangExitPath);
941 };
943
944 me->DespawnOrUnsummon(18s);
945 }
946 }
947
948 void SetData(uint32 type, uint32 data) override
949 {
950 if (type == ACTION_CLEAR_SLOT)
951 {
953 if (data == SLOT_FREEZE_MAGE)
955 }
956 }
957
958 bool OnGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override
959 {
961 if (Transport* transport = dynamic_cast<Transport*>(me->GetTransport()))
962 transport->EnableMovement(true);
969 return false;
970 }
971
972 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
973 {
976
977 if (damage >= me->GetHealth())
978 damage = me->GetHealth() - 1;
979 }
980
981 void UpdateAI(uint32 diff) override
982 {
984 return;
985
986 _events.Update(diff);
987
988 while (uint32 eventId = _events.ExecuteEvent())
989 {
990 switch (eventId)
991 {
992 case EVENT_INTRO_H_1:
994 break;
995 case EVENT_INTRO_H_2:
997 break;
999 sTransportMgr->CreateTransport(GO_THE_SKYBREAKER_H, me->GetMap());
1000 break;
1001 case EVENT_INTRO_H_3:
1003 break;
1004 case EVENT_INTRO_H_4:
1006 break;
1007 case EVENT_INTRO_H_5:
1009 muradin->AI()->Talk(SAY_MURADIN_INTRO_H);
1010 break;
1011 case EVENT_INTRO_H_6:
1013 break;
1016 {
1019 }
1020 break;
1021 case EVENT_SUMMON_MAGE:
1024 break;
1025 case EVENT_ADDS:
1030 if (Transport* orgrimsHammer = dynamic_cast<Transport*>(me->GetTransport()))
1031 orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21s);
1032
1034 skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23s);
1035
1038 break;
1041 muradin->AI()->Talk(SAY_MURADIN_BOARD);
1042 break;
1045 {
1047 {
1050 }
1051 }
1053 break;
1054 case EVENT_CHECK_MORTAR:
1056 {
1058 {
1061 }
1062 }
1064 break;
1065 case EVENT_CLEAVE:
1068 break;
1069 default:
1070 break;
1071 }
1072 }
1073
1075 {
1076 if (me->isAttackReady())
1077 {
1080 }
1081 }
1082 }
1083
1084 bool CanAIAttack(Unit const* target) const override
1085 {
1087 return false;
1089 }
1090
1091private:
1098};
1099
1100// 36948 - Muradin Bronzebeard
1102{
1104 _instance(creature->GetInstanceScript())
1105 {
1107 _controller.SetTransport(dynamic_cast<Transport*>(creature->GetTransport()));
1108 me->SetRegenerateHealth(false);
1109 me->m_CombatDistance = 70.0f;
1111 _riflemanYellCooldown = time_t(0);
1112 _mortarYellCooldown = time_t(0);
1113 }
1114
1115 void InitializeAI() override
1116 {
1118
1119 _events.Reset();
1121 _riflemanYellCooldown = time_t(0);
1122 _mortarYellCooldown = time_t(0);
1123 }
1124
1132
1133 void EnterEvadeMode(EvadeReason /*why*/) override
1134 {
1135 if (!me->IsAlive())
1136 return;
1137
1138 me->CombatStop(true);
1141
1142 Reset();
1143 }
1144
1145 void DoAction(int32 action) override
1146 {
1147 if (action == ACTION_ENEMY_GUNSHIP_TALK)
1148 {
1150 muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS);
1151
1156
1158 // Combat starts now
1159 if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f))
1161
1162 if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f))
1163 {
1165 skybreaker->CastSpell(skybreaker, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK);
1166 }
1167
1169 }
1170 else if (action == ACTION_SPAWN_MAGE)
1171 {
1172 TimePoint now = GameTime::Now();
1173 if (_firstMageCooldown > now)
1174 _events.ScheduleEvent(EVENT_SUMMON_MAGE, std::chrono::duration_cast<Milliseconds>(_firstMageCooldown - now));
1175 else
1177 }
1178 else if (action == ACTION_SPAWN_ALL_ADDS)
1179 {
1183 if (Is25ManRaid())
1185 else
1186 {
1190 }
1191 }
1192 else if (action == ACTION_EXIT_SHIP)
1193 {
1194 std::function<void(Movement::MoveSplineInit&)> initializer = [](Movement::MoveSplineInit& init)
1195 {
1196 init.DisableTransportPathTransformations();
1197 init.MovebyPath(MuradinExitPath);
1198 };
1200
1201 me->DespawnOrUnsummon(18s);
1202 }
1203 }
1204
1205 void SetData(uint32 type, uint32 data) override
1206 {
1207 if (type == ACTION_CLEAR_SLOT)
1208 {
1210 if (data == SLOT_FREEZE_MAGE)
1212 }
1213 }
1214
1215 bool OnGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override
1216 {
1218 if (Transport* transport = dynamic_cast<Transport*>(me->GetTransport()))
1219 transport->EnableMovement(true);
1227 return false;
1228 }
1229
1230 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1231 {
1234
1235 if (damage >= me->GetHealth())
1236 damage = me->GetHealth() - 1;
1237 }
1238
1239 void UpdateAI(uint32 diff) override
1240 {
1242 return;
1243
1244 _events.Update(diff);
1245
1246 while (uint32 eventId = _events.ExecuteEvent())
1247 {
1248 switch (eventId)
1249 {
1250 case EVENT_INTRO_A_1:
1252 break;
1253 case EVENT_INTRO_A_2:
1255 break;
1257 sTransportMgr->CreateTransport(GO_ORGRIMS_HAMMER_A, me->GetMap());
1258 break;
1259 case EVENT_INTRO_A_3:
1261 break;
1262 case EVENT_INTRO_A_4:
1264 break;
1265 case EVENT_INTRO_A_5:
1267 break;
1268 case EVENT_INTRO_A_6:
1270 saurfang->AI()->Talk(SAY_SAURFANG_INTRO_A);
1271 break;
1272 case EVENT_INTRO_A_7:
1274 break;
1277 {
1280 }
1281 break;
1282 case EVENT_SUMMON_MAGE:
1285 break;
1286 case EVENT_ADDS:
1291 if (Transport* skybreaker = dynamic_cast<Transport*>(me->GetTransport()))
1292 skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21s);
1293
1295 orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23s);
1296
1299 break;
1302 saurfang->AI()->Talk(SAY_SAURFANG_BOARD);
1303 break;
1306 {
1308 {
1311 }
1312 }
1314 break;
1315 case EVENT_CHECK_MORTAR:
1317 {
1319 {
1322 }
1323 }
1325 break;
1326 case EVENT_CLEAVE:
1329 break;
1330 default:
1331 break;
1332 }
1333 }
1334
1336 {
1337 if (me->isAttackReady())
1338 {
1341 }
1342 }
1343 }
1344
1345 bool CanAIAttack(Unit const* target) const override
1346 {
1348 return false;
1349 return target->HasAura(SPELL_ON_SKYBREAKER_DECK) || target->GetEntry() == NPC_KOR_KRON_REAVER || target->GetEntry() == NPC_KOR_KRON_SERGEANT;
1350 }
1351
1352private:
1359};
1360
1361// 37184 - Zafod Boombox
1363{
1364 npc_zafod_boombox(Creature* creature) : gunship_npc_AI(creature) { }
1365
1366 void Reset() override
1367 {
1369 }
1370
1371 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override
1372 {
1374 CloseGossipMenuFor(player);
1375 return false;
1376 }
1377
1378 void UpdateAI(uint32 /*diff*/) override
1379 {
1380 UpdateVictim();
1381 }
1382};
1383
1385{
1387 {
1388 me->m_CombatDistance = 80.0f;
1389 _usedDesperateResolve = false;
1390 }
1391
1392 void SetData(uint32 type, uint32 data) override
1393 {
1394 // detach from captain
1395 if (type == ACTION_SET_SLOT)
1396 {
1397 SetSlotInfo(data);
1398
1400
1402
1404 captain->AI()->SetData(ACTION_CLEAR_SLOT, Index);
1405 }
1406 }
1407
1408 void MovementInform(uint32 type, uint32 pointId) override
1409 {
1410 if (type != POINT_MOTION_TYPE)
1411 return;
1412
1413 if (pointId == EVENT_CHARGE_PREPATH && Slot)
1414 {
1416 TransportBase const* myTransport = me->GetTransport();
1417 if (!myTransport)
1418 return;
1419
1421 {
1422 Position globalPosition = destTransport->GetPositionWithOffset(otherTransportPos);
1423
1424 float angle = frand(0, float(M_PI) * 2.0f);
1425 globalPosition.m_positionX += 2.0f * std::cos(angle);
1426 globalPosition.m_positionY += 2.0f * std::sin(angle);
1427
1428 me->SetHomePosition(globalPosition);
1429 me->SetTransportHomePosition(myTransport->GetPositionOffsetTo(globalPosition));
1430 }
1431
1436 me->GetSpellHistory()->AddCooldown(BurningPitchId, 0, std::chrono::seconds(3));
1437
1438 std::list<Player*> players;
1441 Cell::VisitWorldObjects(me, searcher, 200.0f);
1442
1443 players.remove_if([this](Player* player)
1444 {
1445 return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true);
1446 });
1447
1448 if (!players.empty())
1449 {
1450 players.sort(Trinity::ObjectDistanceOrderPred(me));
1451 for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
1452 AddThreat(*itr, 1.0f);
1453
1454 AttackStart(players.front());
1455 }
1456
1458 }
1459 }
1460
1461 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1462 {
1464 return;
1465
1466 if (!me->HealthBelowPctDamaged(25, damage))
1467 return;
1468
1469 _usedDesperateResolve = true;
1471 }
1472
1473 void UpdateAI(uint32 /*diff*/) override
1474 {
1475 if (!SelectVictim())
1476 {
1478 return;
1479 }
1480
1483 }
1484
1485 bool CanAIAttack(Unit const* target) const override
1486 {
1488 uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD;
1490 {
1492 creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG;
1493 }
1494
1495 return target->HasAura(spellId) || target->GetEntry() == creatureEntry;
1496 }
1497
1499 {
1500 std::list<Player*> players;
1503 Cell::VisitWorldObjects(me, searcher,200.0f );
1504
1505 players.remove_if([this](Player* player)
1506 {
1507 return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true);
1508 });
1509
1510 return !players.empty();
1511 }
1512
1513private:
1515};
1516
1517// 36960 - Kor'kron Sergeant
1518// 36961 - Skybreaker Sergeant
1520{
1522
1529
1530 void UpdateAI(uint32 diff) override
1531 {
1532 if (!SelectVictim())
1533 {
1535 return;
1536 }
1537
1538 _events.Update(diff);
1539
1541 return;
1542
1545
1546 while (uint32 eventId = _events.ExecuteEvent())
1547 {
1548 switch (eventId)
1549 {
1550 case EVENT_BLADESTORM:
1553 break;
1557 break;
1558 default:
1559 break;
1560 }
1561 }
1562 }
1563
1564private:
1566};
1567
1568// 36950 - Skybreaker Marine
1569// 36957 - Kor'kron Reaver
1571{
1572 public:
1573 npc_gunship_boarding_add() : CreatureScript("npc_gunship_boarding_add") { }
1574
1575 CreatureAI* GetAI(Creature* creature) const override
1576 {
1577 return GetIcecrownCitadelAI<npc_gunship_boarding_addAI>(creature);
1578 }
1579};
1580
1581// 36968 - Kor'kron Axethrower
1582// 36969 - Skybreaker Rifleman
1584{
1586 {
1587 creature->m_CombatDistance = 200.0f;
1588 }
1589
1590 void AttackStart(Unit* target) override
1591 {
1592 me->Attack(target, false);
1593 }
1594
1595 void MovementInform(uint32 type, uint32 pointId) override
1596 {
1597 gunship_npc_AI::MovementInform(type, pointId);
1598 if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH)
1600 }
1601
1602 void UpdateAI(uint32 /*diff*/) override
1603 {
1604 if (!SelectVictim())
1605 {
1607 return;
1608 }
1609
1611 }
1612};
1613
1614// 36978 - Skybreaker Mortar Soldier
1615// 36982 - Kor'kron Rocketeer
1617{
1619 {
1620 creature->m_CombatDistance = 200.0f;
1621 }
1622
1623 void MovementInform(uint32 type, uint32 pointId) override
1624 {
1625 gunship_npc_AI::MovementInform(type, pointId);
1626 if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH)
1628 }
1629
1630 void UpdateAI(uint32 /*diff*/) override
1631 {
1632 if (!SelectVictim())
1633 return;
1634
1636 return;
1637
1639 if (me->GetSpellHistory()->HasCooldown(spellId))
1640 return;
1641
1642 DoCastAOE(spellId, true);
1643 me->GetSpellHistory()->AddCooldown(spellId, 0, std::chrono::seconds(9));
1644 }
1645};
1646
1647// 37116 - Skybreaker Sorcerer
1648// 37117 - Kor'kron Battle-Mage
1650{
1652 {
1654 }
1655
1656 void EnterEvadeMode(EvadeReason /*why*/) override { }
1657
1658 void MovementInform(uint32 type, uint32 pointId) override
1659 {
1660 if (type != POINT_MOTION_TYPE)
1661 return;
1662
1663 if (pointId == EVENT_CHARGE_PREPATH && Slot)
1664 {
1666 me->SetFacingTo(slots[Index].TargetPosition.GetOrientation());
1667 switch (Index)
1668 {
1669 case SLOT_FREEZE_MAGE:
1671 break;
1672 case SLOT_MAGE_1:
1673 case SLOT_MAGE_2:
1675 break;
1676 default:
1677 break;
1678 }
1679
1681 }
1682 }
1683
1684 void UpdateAI(uint32 /*diff*/) override
1685 {
1686 UpdateVictim();
1687 }
1688
1689 bool CanAIAttack(Unit const* /*target*/) const override
1690 {
1691 return true;
1692 }
1693};
1694
1715// 36838 - Alliance Gunship Cannon
1716// 36839 - Horde Gunship Cannon
1718{
1719 npc_gunship_cannon(Creature* creature) : PassiveAI(creature) { }
1720
1721 void OnCharmed(bool /*isNew*/) override { }
1722
1723 void PassengerBoarded(Unit* /*passenger*/, int8 /*seat*/, bool apply) override
1724 {
1725 if (!apply)
1726 {
1729 }
1730 }
1731};
1732
1733// 68721 - Rocket Pack
1764
1765// 70348 - Rocket Pack Useable
1767{
1768 bool Load() override
1769 {
1770 return GetOwner()->GetInstanceScript() != nullptr;
1771 }
1772
1773 bool CheckAreaTarget(Unit* target)
1774 {
1776 }
1777
1778 void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1779 {
1780 if (Creature* owner = GetOwner()->ToCreature())
1781 if (Player* target = GetTarget()->ToPlayer())
1782 if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1))
1784 }
1785
1786 void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1787 {
1788 if (Creature* owner = GetOwner()->ToCreature())
1789 if (Player* target = GetTarget()->ToPlayer())
1790 if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1))
1792 }
1793
1800};
1801
1802// 70120 - On Skybreaker Deck
1803// 70121 - On Orgrim's Hammer Deck
1805{
1806public:
1811
1812private:
1813 bool Load() override
1814 {
1815 if (InstanceScript* instance = GetOwner()->GetInstanceScript())
1816 _teamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
1817 else
1818 _teamInInstance = 0;
1819 return true;
1820 }
1821
1823 {
1824 return unit->GetTypeId() == TYPEID_PLAYER;
1825 }
1826
1833
1839
1841};
1842
1843// 69470 - Heat Drain
1844// 69487 - Overheat
1858
1859// 69399, 70172 - Cannon Blast
1861{
1862 bool Load() override
1863 {
1864 return GetCaster()->GetTypeId() == TYPEID_UNIT;
1865 }
1866
1868 {
1869 if (GetCaster()->GetPower(POWER_ENERGY) >= 100)
1870 {
1872 if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
1873 if (Unit* passenger = vehicle->GetPassenger(0))
1874 sCreatureTextMgr->SendChat(GetCaster()->ToCreature(), SAY_OVERHEAT, passenger);
1875 }
1876 }
1877
1878 void Register() override
1879 {
1881 }
1882};
1883
1884// 69402, 70175 - Incinerating Blast
1886{
1888 {
1890 }
1891
1893 {
1895 }
1896
1897 void CalculateDamage(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/) const
1898 {
1899 flatMod += _energyLeft * _energyLeft * 8;
1900 }
1901
1908
1910};
1911
1912// 69487 - Overheat
1914{
1915 bool Load() override
1916 {
1917 if (GetAura()->GetType() != UNIT_AURA_TYPE)
1918 return false;
1919 return GetUnitOwner()->IsVehicle();
1920 }
1921
1922 void SendClientControl(bool value)
1923 {
1924 if (Vehicle* vehicle = GetUnitOwner()->GetVehicleKit())
1925 {
1926 if (Unit* passenger = vehicle->GetPassenger(0))
1927 {
1928 if (Player* player = passenger->ToPlayer())
1929 {
1931 data.Guid = GetUnitOwner()->GetGUID();
1932 data.On = value;
1933 player->SendDirectMessage(data.Write());
1934 }
1935 }
1936 }
1937 }
1938
1939 void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1940 {
1941 SendClientControl(false);
1942 }
1943
1944 void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1945 {
1946 SendClientControl(true);
1947 }
1948
1954};
1955
1956// 69705 - Below Zero
1958{
1960 {
1961 if (missInfo != SPELL_MISS_NONE)
1962 return;
1963
1965 }
1966
1971};
1972
1973// 70104 - Teleport to Enemy Ship
1975{
1977 {
1978 WorldLocation const* dest = GetHitDest();
1979 Unit* target = GetHitUnit();
1980 if (!dest || !target || !target->GetTransport())
1981 return;
1982
1984 }
1985
1990};
1991
1992// 70397, 70403 - Burning Pitch
1994{
1995 void FilterTargets(std::list<WorldObject*>& targets)
1996 {
1997 uint32 team = HORDE;
1998 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
1999 team = instance->GetData(DATA_TEAM_IN_INSTANCE);
2000
2001 targets.remove_if([team](WorldObject* target) -> bool
2002 {
2003 if (Transport* transport = dynamic_cast<Transport*>(target->GetTransport()))
2004 return transport->GetEntry() != uint32(team == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A);
2005 return true;
2006 });
2007
2008 if (!targets.empty())
2009 {
2011 targets.clear();
2012 targets.push_back(target);
2013 }
2014 }
2015
2021
2027};
2028
2029// 71335, 71339 - Burning Pitch
2046
2047// 69678, 70609 - Rocket Artillery
2049{
2050 void SelectRandomTarget(std::list<WorldObject*>& targets)
2051 {
2052 if (!targets.empty())
2053 {
2055 targets.clear();
2056 targets.push_back(target);
2057 }
2058 }
2059
2065
2071};
2072
2073// 69679 - Rocket Artillery
2075{
2076 void DamageGunship(SpellEffIndex /*effIndex*/)
2077 {
2078 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
2079 {
2081 args.AddSpellBP0(5000);
2083 }
2084 }
2085
2090};
2091
2092// 67335 - Gunship Fall Teleport
2094{
2095 bool Load() override
2096 {
2097 return GetCaster()->GetInstanceScript() != nullptr;
2098 }
2099
2101 {
2102 if (InstanceScript* instance = target->GetInstanceScript())
2103 target = ObjectAccessor::GetTransport(*GetCaster(), instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE));
2104 }
2105
2106 void RelocateDest(SpellEffIndex /*effIndex*/)
2107 {
2108 if (GetCaster()->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE) == HORDE)
2109 GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 36.0f, 0.0f });
2110 else
2111 GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 21.0f, 0.0f });
2112 }
2113
2119};
2120
2121// 70331 - Check for Players
2123{
2124public:
2129
2130private:
2131 bool Load() override
2132 {
2133 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2134 }
2135
2136 void CountTargets(std::list<WorldObject*>& targets)
2137 {
2138 _playerCount = targets.size();
2139 }
2140
2142 {
2143 if (!_playerCount)
2144 GetCaster()->ToCreature()->AI()->JustDied(nullptr);
2145 }
2146
2148 {
2149 if (GetHitUnit()->GetPositionZ() < GetCaster()->GetPositionZ() - 10.0f)
2151 }
2152
2159
2161};
2162
2163// 72340 - Teleport Players on Victory
2165{
2166 bool Load() override
2167 {
2168 return GetCaster()->GetInstanceScript() != nullptr;
2169 }
2170
2171 void FilterTargets(std::list<WorldObject*>& targets)
2172 {
2174 targets.remove_if([instance](WorldObject* target) -> bool
2175 {
2176 return target->GetTransGUID() != instance->GetGuidData(DATA_ENEMY_GUNSHIP);
2177 });
2178 }
2179
2184};
2185
2186// 71201 - Battle Experience - proc should never happen, handled in script
2188{
2189 bool CheckProc(ProcEventInfo& /*eventInfo*/)
2190 {
2191 return false;
2192 }
2193
2198};
2199
2201{
2202 public:
2203 achievement_im_on_a_boat() : AchievementCriteriaScript("achievement_im_on_a_boat") { }
2204
2205 bool OnCheck(Player* /*source*/, Unit* target) override
2206 {
2207 return target->GetAI() && target->GetAI()->GetData(ACTION_SHIP_VISITS) <= 2;
2208 }
2209};
2210
2212{
2213 // Creatures
2214 new npc_gunship();
2224
2225 // Spells
2243
2244 // Achievements
2246}
#define M_PI
Definition Common.h:118
#define sCreatureTextMgr
@ TEXT_RANGE_NORMAL
uint8_t uint8
Definition Define.h:156
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
Definition Duration.h:40
#define SIZE_OF_GRIDS
Definition GridDefines.h:40
@ IN_PROGRESS
@ FAIL
@ DONE
@ ENCOUNTER_FRAME_DISENGAGE
@ ENCOUNTER_FRAME_ENGAGE
@ MOTION_PRIORITY_NORMAL
@ POINT_MOTION_TYPE
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_CORPSE_TIMED_DESPAWN
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
float frand(float min, float max)
Definition Random.cpp:56
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
void CloseGossipMenuFor(Player *player)
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_TRIGGER_MISSILE
@ SPELL_EFFECT_TELEPORT_UNITS
@ LANG_ADDON
SpellMissInfo
@ SPELL_MISS_NONE
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_DEST_NEARBY_ENTRY
@ TARGET_UNIT_SRC_AREA_ENEMY
@ TARGET_UNIT_DEST_AREA_ENTRY
@ EVENT_CHARGE_PREPATH
@ TEAM_OTHER
@ ALLIANCE
@ HORDE
@ POWER_ENERGY
@ CHAT_MSG_ADDON
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ AURA_REMOVE_BY_EXPIRE
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ UNIT_AURA_TYPE
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ TRIGGERED_IGNORE_POWER_COST
Will ignore power and reagent cost.
@ TRIGGERED_NONE
Not triggered.
#define sSpellMgr
Definition SpellMgr.h:812
#define BeforeSpellHitFn(F)
#define SpellObjectTargetSelectFn(F, I, N)
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define SpellCalcDamageFn(F)
#define SpellCastFn(F)
#define AuraEffectApplyFn(F, I, N, M)
#define AuraCheckProcFn(F)
#define SpellHitFn(F)
#define AuraCheckAreaTargetFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
#define sTransportMgr
EvadeReason
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_NPC_FLAG_GOSSIP
DamageEffectType
@ UNIT_STATE_ROOT
Definition Unit.h:285
@ UNIT_STATE_CASTING
Definition Unit.h:290
G3D::Vector3 const SaurfangExitPath[]
@ SAY_MURADIN_ENTER_ORGRIMMS_HAMMER
SlotInfo const SkybreakerSlotInfo[MAX_SLOTS]
G3D::Vector3 const MuradinExitPath[]
Position const SkybreakerTeleportPortal
Position const OrgrimsHammerTeleportPortal
Position const OrgrimsHammerTeleportExit
@ SPELL_MELEE_TARGETING_ON_SKYBREAKER
@ SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER
@ SPELL_TELEPORT_PLAYERS_ON_RESET_H
@ SPELL_TELEPORT_PLAYERS_ON_RESET_A
@ SPELL_TELEPORT_PLAYERS_ON_VICTORY
@ SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO
SlotInfo const OrgrimsHammerSlotInfo[MAX_SLOTS]
Position const SkybreakerAddsSpawnPos
Position const OrgrimsHammerAddsSpawnPos
void AddSC_boss_icecrown_gunship_battle()
Position const SkybreakerTeleportExit
@ EVENT_INTRO_SUMMON_ORGRIMS_HAMMER
uint32 GetTickNumber() const
SpellEffectInfo const & GetSpellEffectInfo() const
int32 GetPeriod() const
void PreventDefaultAction()
AuraObjectType GetType() const
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
SpellInfo const * GetSpellInfo() const
WorldObject * GetOwner() const
HookList< EffectApplyHandler > AfterEffectApply
Aura * GetAura() const
HookList< CheckAreaTargetHandler > DoCheckAreaTarget
Unit * GetTarget() const
Difficulty GetCastDifficulty() const
HookList< CheckProcHandler > DoCheckProc
HookList< EffectApplyHandler > OnEffectRemove
Unit * GetUnitOwner() const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
TypeID GetTypeId() const
Definition BaseEntity.h:166
bool Execute(uint64 timer, uint32) override
static uint32 const ExperiencedSpells[5]
static Milliseconds const ExperiencedTimes[5]
virtual void JustEngagedWith(Unit *)
Definition CreatureAI.h:101
virtual void JustDied(Unit *)
Definition CreatureAI.h:107
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void EngagementOver()
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:394
bool _IsTargetAcceptable(Unit const *target) const
bool HasReactState(ReactStates state) const
Definition Creature.h:182
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetRegenerateHealth(bool value)
Definition Creature.h:381
float m_CombatDistance
Definition Creature.h:435
Unit * SelectVictim()
void SetTransportHomePosition(float x, float y, float z, float o)
Definition Creature.h:399
CreatureAI * AI() const
Definition Creature.h:235
bool CanStartAttack(Unit const *u, bool force) const
bool HasSpellFocus(Spell const *focusSpell=nullptr) const override
DelayedMovementEvent(Creature *owner, Position const &dest)
bool Execute(uint64, uint32) override
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:246
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:32
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
void AddEventAtOffset(BasicEvent *event, Milliseconds offset)
Milliseconds CalculateTime(Milliseconds t_offset) const
virtual bool SetBossState(uint32 id, EncounterState state)
void DoCastSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
void SendEncounterUnit(EncounterFrameType type, Unit const *unit, Optional< int32 > param1={}, Optional< int32 > param2={})
void SetZoneMusic(uint32 zoneId, uint32 musicId)
Definition Map.cpp:4021
bool IsHeroic() const
Definition Map.cpp:3347
void LaunchMoveSpline(std::function< void(Movement::MoveSplineInit &init)> &&initializer, uint32 id=0, MovementGeneratorPriority priority=MOTION_PRIORITY_NORMAL, MovementGeneratorType type=EFFECT_MOTION_TYPE, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
void MoveTargetedHome()
void Clear()
Definition ObjectGuid.h:329
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
void SetTransport(Transport *transport)
bool SlotsNeedRefill(GunshipPassengerSlots first, GunshipPassengerSlots last) const
bool SummonCreatures(GunshipPassengerSlots first, GunshipPassengerSlots last)
void ClearSlot(GunshipPassengerSlots slot)
ObjectGuid _controlledSlots[MAX_SLOTS]
ResetEncounterEvent(Unit *caster, uint32 spellId, ObjectGuid transport, ObjectGuid otherTransport)
bool Execute(uint64, uint32) override
SpellEffectValue CalcValue(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
uint32 TriggerSpell
Definition SpellInfo.h:234
void AddCooldown(uint32 spellId, uint32 itemId, Duration cooldownDuration)
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0) const
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:590
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
static bool ValidateSpellEffect(std::initializer_list< std::pair< uint32, SpellEffIndex > > effects)
HookList< DamageAndHealingCalcHandler > CalcDamage
HookList< CastHandler > AfterCast
WorldLocation * GetHitDest() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
int32 GetEffectValueAsInt() const
HookList< EffectHandler > OnEffectHit
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
HookList< ObjectTargetSelectHandler > OnObjectTargetSelect
HookList< CastHandler > OnCast
HookList< BeforeHitHandler > BeforeHit
HookList< EffectHandler > OnEffectLaunch
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
bool IsThreatListEmpty(bool includeOffline=false) const
virtual ObjectGuid GetTransportGUID() const =0
virtual Position GetPositionOffsetTo(Position const &endPos) const =0
This method transforms supplied global coordinates into local offsets.
virtual Position GetPositionWithOffset(Position const &offset) const =0
This method transforms supplied transport offsets into global coordinates.
TempSummon * SummonPassenger(uint32 entry, Position const &pos, TempSummonType summonType, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, Unit *summoner=nullptr, uint32 spellId=0, uint32 vehId=0)
Temporarily summons a creature as passenger on this transport.
bool DoSpellAttackIfReady(uint32 spellId)
Definition UnitAI.cpp:53
virtual void Reset()
Definition UnitAI.h:64
virtual void InitializeAI()
Definition UnitAI.cpp:35
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
virtual uint32 GetData(uint32 id) const
Definition UnitAI.h:74
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
bool IsVehicle() const
Definition Unit.h:766
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:722
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6031
ThreatManager & GetThreatManager()
Definition Unit.h:1093
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11631
void SetPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:10114
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool IsAlive() const
Definition Unit.h:1205
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1013
UnitAI * GetAI() const
Definition Unit.h:680
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5872
uint64 GetHealth() const
Definition Unit.h:800
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:805
Unit * GetVictim() const
Definition Unit.h:738
int32 GetPower(Powers power) const
Definition Unit.cpp:10096
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
void RemoveAllAuras()
Definition Unit.cpp:4400
SpellHistory * GetSpellHistory()
Definition Unit.h:1521
void RemoveVehicleKit(bool onRemoveFromWorld=false)
Definition Unit.cpp:12185
bool isAttackReady(WeaponAttackType type=BASE_ATTACK) const
Definition Unit.h:713
void resetAttackTimer(WeaponAttackType type=BASE_ATTACK)
Definition Unit.cpp:670
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
bool IsInCombat() const
Definition Unit.h:1073
Map * GetMap() const
Definition Object.h:411
InstanceScript * GetInstanceScript() const
Definition Object.cpp:394
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
TransportBase * GetTransport() const
Definition Object.h:537
virtual ObjectGuid GetTransGUID() const
Definition Object.cpp:3096
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1522
EventProcessor m_Events
Definition Object.h:561
MovementInfo m_movementInfo
Definition Object.h:548
WorldPacket const * Write() override
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:99
bool OnCheck(Player *, Unit *target) override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
void RemovePassengers(SpellMissInfo missInfo)
void FilterTargets(std::list< WorldObject * > &targets)
void HandleDummy(SpellEffIndex effIndex)
void CountTargets(std::list< WorldObject * > &targets)
void CalculateDamage(SpellEffectInfo const &, Unit const *, int32 &, int32 &flatMod, float &) const
void HandleApply(AuraEffect const *, AuraEffectHandleModes)
void HandleRemove(AuraEffect const *, AuraEffectHandleModes)
void HandleApply(AuraEffect const *, AuraEffectHandleModes)
void SelectRandomTarget(std::list< WorldObject * > &targets)
void HandleScript(SpellEffIndex effIndex)
void HandleApply(AuraEffect const *, AuraEffectHandleModes)
void HandleRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
void HandlePeriodic(AuraEffect const *)
void HandleRemove(AuraEffect const *aurEff, AuraEffectHandleModes)
void FilterTargets(std::list< WorldObject * > &targets)
@ DATA_TEAM_IN_INSTANCE
#define RegisterIcecrownCitadelCreatureAI(ai_name)
@ AREA_ICECROWN_CITADEL
@ GO_THE_SKYBREAKER_A
@ GO_THE_SKYBREAKER_H
@ GO_ORGRIMS_HAMMER_A
@ GO_ORGRIMS_HAMMER_H
@ ACTION_ENEMY_GUNSHIP_TALK
@ ACTION_EXIT_SHIP
@ DATA_ICECROWN_GUNSHIP_BATTLE
@ DATA_ENEMY_GUNSHIP
@ NPC_TELEPORT_PORTAL
@ NPC_SKYBREAKER_SORCERER
@ NPC_ORGRIMS_HAMMER
@ NPC_IGB_MURADIN_BRONZEBEARD
@ NPC_SKYBREAKER_MARINE
@ NPC_KOR_KRON_ROCKETEER
@ NPC_SKYBREAKER_MORTAR_SOLDIER
@ NPC_TELEPORT_EXIT
@ NPC_KOR_KRON_BATTLE_MAGE
@ NPC_KOR_KRON_REAVER
@ NPC_MARTYR_STALKER_IGB_SAURFANG
@ NPC_KOR_KRON_AXETHROWER
@ NPC_KOR_KRON_SERGEANT
@ NPC_IGB_HIGH_OVERLORD_SAURFANG
@ NPC_SKYBREAKER_RIFLEMAN
@ NPC_SKYBREAKER_SERGEANT
@ NPC_GUNSHIP_HULL
@ NPC_THE_SKYBREAKER
@ NPC_ALLIANCE_GUNSHIP_CANNON
@ NPC_HORDE_GUNSHIP_CANNON
TimePoint Now()
Current chrono steady_clock time point.
Definition GameTime.cpp:67
time_t GetGameTime()
Definition GameTime.cpp:52
TC_GAME_API Transport * GetTransport(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
Definition Containers.h:110
CastSpellExtraArgs & SetCastDifficulty(Difficulty castDifficulty)
CastSpellExtraArgs & AddSpellBP0(SpellEffectValue val)
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:150
struct MovementInfo::TransportInfo transport
constexpr void SetOrientation(float orientation)
Definition Position.h:82
constexpr float GetPositionX() const
Definition Position.h:87
float m_positionZ
Definition Position.h:66
constexpr float GetPositionY() const
Definition Position.h:88
Position GetPositionWithOffset(Position const &offset) const
Definition Position.cpp:61
float m_positionX
Definition Position.h:64
float m_positionY
Definition Position.h:65
constexpr void Relocate(float x, float y)
Definition Position.h:74
void RelocateOffset(Position const &offset)
Definition Position.cpp:34
constexpr float GetOrientation() const
Definition Position.h:90
constexpr float GetPositionZ() const
Definition Position.h:89
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
bool Is25ManRaid() const
void AddThreat(Unit *victim, float amount, Unit *who=nullptr)
gunship_npc_AI(Creature *creature)
void MovementInform(uint32 type, uint32 pointId) override
void EnterEvadeMode(EvadeReason) override
bool CanAIAttack(Unit const *target) const override
void SetData(uint32 type, uint32 data) override
void JustDied(Unit *) override
uint32 GetData(uint32 id) const override
std::map< ObjectGuid, uint32 > _shipVisits
void SetGUID(ObjectGuid const &guid, int32 id) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void SetData(uint32 type, uint32 data) override
bool CanAIAttack(Unit const *target) const override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void MovementInform(uint32 type, uint32 pointId) override
void JustEngagedWith(Unit *target) override
void PassengerBoarded(Unit *, int8, bool apply) override
== Fields =======================================
void AttackStart(Unit *target) override
== Triggered Actions Requested ==================
void MovementInform(uint32 type, uint32 pointId) override
void EnterEvadeMode(EvadeReason) override
bool CanAIAttack(Unit const *) const override
void MovementInform(uint32 type, uint32 pointId) override
void MovementInform(uint32 type, uint32 pointId) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void SetData(uint32 type, uint32 data) override
bool CanAIAttack(Unit const *target) const override
bool OnGossipSelect(Player *, uint32, uint32) override
bool OnGossipSelect(Player *, uint32, uint32) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
bool CanAIAttack(Unit const *target) const override
void SetData(uint32 type, uint32 data) override
bool OnGossipSelect(Player *player, uint32, uint32) override