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
668{
669 public:
670 npc_gunship() : CreatureScript("npc_gunship") { }
671
673 {
674 npc_gunshipAI(Creature* creature) : NullCreatureAI(creature),
675 _teamInInstance(creature->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE)),
676 _summonedFirstMage(false), _died(false)
677 {
678 me->SetRegenerateHealth(false);
679 }
680
681 void DamageTaken(Unit* /*source*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
682 {
683 if (damage >= me->GetHealth())
684 {
685 JustDied(nullptr);
686 damage = me->GetHealth() - 1;
687 return;
688 }
689
691 return;
692
694 return;
695
696 if (!me->HealthBelowPctDamaged(90, damage))
697 return;
698
699 _summonedFirstMage = true;
701 captain->AI()->DoAction(ACTION_SPAWN_MAGE);
702 }
703
704 void JustDied(Unit* /*killer*/) override
705 {
706 if (_died)
707 return;
708
709 _died = true;
710
711 InstanceScript* instance = me->GetInstanceScript();
712 bool isVictory = me->GetTransport()->GetTransportGUID() == instance->GetGuidData(DATA_ENEMY_GUNSHIP);
713 instance->SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, isVictory ? DONE : FAIL);
715 {
716 instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, creature);
717 creature->RemoveAurasDueToSpell(SPELL_CHECK_FOR_PLAYERS);
718 }
719
722
724 std::list<Creature*> creatures;
726 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
727 {
728 Creature* stalker = *itr;
729 stalker->RemoveAllAuras();
730 stalker->CombatStop(true);
731 }
732
733 uint32 explosionSpell = isVictory ? SPELL_EXPLOSION_VICTORY : SPELL_EXPLOSION_WIPE;
734 creatures.clear();
736 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
737 {
738 Creature* hull = *itr;
739 if (hull->GetTransport() != me->GetTransport())
740 continue;
741
742 hull->CastSpell(hull, explosionSpell, TRIGGERED_FULL_MASK);
743 }
744
745 creatures.clear();
747 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
748 {
749 Creature* cannon = *itr;
750 if (isVictory)
751 {
753 cannon->RemoveVehicleKit();
754 }
755 else
757 }
758
759 uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD;
760 uint8 textId = isVictory ? SAY_MURADIN_VICTORY : SAY_MURADIN_WIPE;
761 if (_teamInInstance == HORDE)
762 {
763 creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG;
764 textId = isVictory ? SAY_SAURFANG_VICTORY : SAY_SAURFANG_WIPE;
765 }
766
767 if (Creature* creature = me->FindNearestCreature(creatureEntry, 100.0f))
768 creature->AI()->Talk(textId);
769
770 if (isVictory)
771 {
773 otherTransport->EnableMovement(true);
774
775 if (Transport* transport = dynamic_cast<Transport*>(me->GetTransport()))
776 transport->EnableMovement(true);
777
779 {
781 ship->CastSpell(ship, SPELL_ACHIEVEMENT, TRIGGERED_FULL_MASK);
783 }
784
785 creatures.clear();
790 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
791 (*itr)->DespawnOrUnsummon(1ms);
792 }
793 else
794 {
797 instance->GetGuidData(DATA_ENEMY_GUNSHIP)), 8s);
798 }
799 }
800
801 void SetGUID(ObjectGuid const& guid, int32 id) override
802 {
803 if (id != ACTION_SHIP_VISITS)
804 return;
805
806 std::map<ObjectGuid, uint32>::iterator itr = _shipVisits.find(guid);
807 if (itr == _shipVisits.end())
808 _shipVisits[guid] = 1;
809 else
810 ++itr->second;
811 }
812
813 uint32 GetData(uint32 id) const override
814 {
815 if (id != ACTION_SHIP_VISITS)
816 return 0;
817
818 uint32 max = 0;
819 for (std::map<ObjectGuid, uint32>::const_iterator itr = _shipVisits.begin(); itr != _shipVisits.end(); ++itr)
820 max = std::max(max, itr->second);
821
822 return max;
823 }
824
825 private:
827 std::map<ObjectGuid, uint32> _shipVisits;
829 bool _died;
830 };
831
832 CreatureAI* GetAI(Creature* creature) const override
833 {
834 if (!creature->GetTransport())
835 return nullptr;
836
837 return GetIcecrownCitadelAI<npc_gunshipAI>(creature);
838 }
839};
840
842{
844 _instance(creature->GetInstanceScript())
845 {
847 _controller.SetTransport(dynamic_cast<Transport*>(creature->GetTransport()));
848 me->SetRegenerateHealth(false);
849 me->m_CombatDistance = 70.0f;
851 _axethrowersYellCooldown = time_t(0);
852 _rocketeersYellCooldown = time_t(0);
853 }
854
855 void InitializeAI() override
856 {
858
859 _events.Reset();
861 _axethrowersYellCooldown = time_t(0);
862 _rocketeersYellCooldown = time_t(0);
863 }
864
872
873 void EnterEvadeMode(EvadeReason /*why*/) override
874 {
875 if (!me->IsAlive())
876 return;
877
878 me->CombatStop(true);
881
882 Reset();
883 }
884
885 void DoAction(int32 action) override
886 {
887 if (action == ACTION_ENEMY_GUNSHIP_TALK)
888 {
890 muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS);
891
896
898 // Combat starts now
899 if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f))
901
902 if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f))
903 {
905 orgrimsHammer->CastSpell(orgrimsHammer, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK);
906 }
907
909 }
910 else if (action == ACTION_SPAWN_MAGE)
911 {
912 TimePoint now = GameTime::Now();
913 if (_firstMageCooldown > now)
914 _events.ScheduleEvent(EVENT_SUMMON_MAGE, std::chrono::duration_cast<Milliseconds>(_firstMageCooldown - now));
915 else
917 }
918 else if (action == ACTION_SPAWN_ALL_ADDS)
919 {
923 if (Is25ManRaid())
925 else
926 {
930 }
931 }
932 else if (action == ACTION_EXIT_SHIP)
933 {
934 std::function<void(Movement::MoveSplineInit&)> initializer = [](Movement::MoveSplineInit& init)
935 {
936 init.DisableTransportPathTransformations();
937 init.MovebyPath(SaurfangExitPath);
938 };
940
941 me->DespawnOrUnsummon(18s);
942 }
943 }
944
945 void SetData(uint32 type, uint32 data) override
946 {
947 if (type == ACTION_CLEAR_SLOT)
948 {
950 if (data == SLOT_FREEZE_MAGE)
952 }
953 }
954
955 bool OnGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override
956 {
958 if (Transport* transport = dynamic_cast<Transport*>(me->GetTransport()))
959 transport->EnableMovement(true);
966 return false;
967 }
968
969 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
970 {
973
974 if (damage >= me->GetHealth())
975 damage = me->GetHealth() - 1;
976 }
977
978 void UpdateAI(uint32 diff) override
979 {
981 return;
982
983 _events.Update(diff);
984
985 while (uint32 eventId = _events.ExecuteEvent())
986 {
987 switch (eventId)
988 {
989 case EVENT_INTRO_H_1:
991 break;
992 case EVENT_INTRO_H_2:
994 break;
996 sTransportMgr->CreateTransport(GO_THE_SKYBREAKER_H, me->GetMap());
997 break;
998 case EVENT_INTRO_H_3:
1000 break;
1001 case EVENT_INTRO_H_4:
1003 break;
1004 case EVENT_INTRO_H_5:
1006 muradin->AI()->Talk(SAY_MURADIN_INTRO_H);
1007 break;
1008 case EVENT_INTRO_H_6:
1010 break;
1013 {
1016 }
1017 break;
1018 case EVENT_SUMMON_MAGE:
1021 break;
1022 case EVENT_ADDS:
1027 if (Transport* orgrimsHammer = dynamic_cast<Transport*>(me->GetTransport()))
1028 orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21s);
1029
1031 skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23s);
1032
1035 break;
1038 muradin->AI()->Talk(SAY_MURADIN_BOARD);
1039 break;
1042 {
1044 {
1047 }
1048 }
1050 break;
1051 case EVENT_CHECK_MORTAR:
1053 {
1055 {
1058 }
1059 }
1061 break;
1062 case EVENT_CLEAVE:
1065 break;
1066 default:
1067 break;
1068 }
1069 }
1070
1072 {
1073 if (me->isAttackReady())
1074 {
1077 }
1078 }
1079 }
1080
1081 bool CanAIAttack(Unit const* target) const override
1082 {
1084 return false;
1086 }
1087
1088private:
1095};
1096
1098{
1100 _instance(creature->GetInstanceScript())
1101 {
1103 _controller.SetTransport(dynamic_cast<Transport*>(creature->GetTransport()));
1104 me->SetRegenerateHealth(false);
1105 me->m_CombatDistance = 70.0f;
1107 _riflemanYellCooldown = time_t(0);
1108 _mortarYellCooldown = time_t(0);
1109 }
1110
1111 void InitializeAI() override
1112 {
1114
1115 _events.Reset();
1117 _riflemanYellCooldown = time_t(0);
1118 _mortarYellCooldown = time_t(0);
1119 }
1120
1128
1129 void EnterEvadeMode(EvadeReason /*why*/) override
1130 {
1131 if (!me->IsAlive())
1132 return;
1133
1134 me->CombatStop(true);
1137
1138 Reset();
1139 }
1140
1141 void DoAction(int32 action) override
1142 {
1143 if (action == ACTION_ENEMY_GUNSHIP_TALK)
1144 {
1146 muradin->AI()->DoAction(ACTION_SPAWN_ALL_ADDS);
1147
1152
1154 // Combat starts now
1155 if (Creature* orgrimsHammer = me->FindNearestCreature(NPC_ORGRIMS_HAMMER, 100.0f))
1157
1158 if (Creature* skybreaker = me->FindNearestCreature(NPC_THE_SKYBREAKER, 100.0f))
1159 {
1161 skybreaker->CastSpell(skybreaker, SPELL_CHECK_FOR_PLAYERS, TRIGGERED_FULL_MASK);
1162 }
1163
1165 }
1166 else if (action == ACTION_SPAWN_MAGE)
1167 {
1168 TimePoint now = GameTime::Now();
1169 if (_firstMageCooldown > now)
1170 _events.ScheduleEvent(EVENT_SUMMON_MAGE, std::chrono::duration_cast<Milliseconds>(_firstMageCooldown - now));
1171 else
1173 }
1174 else if (action == ACTION_SPAWN_ALL_ADDS)
1175 {
1179 if (Is25ManRaid())
1181 else
1182 {
1186 }
1187 }
1188 else if (action == ACTION_EXIT_SHIP)
1189 {
1190 std::function<void(Movement::MoveSplineInit&)> initializer = [](Movement::MoveSplineInit& init)
1191 {
1192 init.DisableTransportPathTransformations();
1193 init.MovebyPath(MuradinExitPath);
1194 };
1196
1197 me->DespawnOrUnsummon(18s);
1198 }
1199 }
1200
1201 void SetData(uint32 type, uint32 data) override
1202 {
1203 if (type == ACTION_CLEAR_SLOT)
1204 {
1206 if (data == SLOT_FREEZE_MAGE)
1208 }
1209 }
1210
1211 bool OnGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override
1212 {
1214 if (Transport* transport = dynamic_cast<Transport*>(me->GetTransport()))
1215 transport->EnableMovement(true);
1223 return false;
1224 }
1225
1226 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1227 {
1230
1231 if (damage >= me->GetHealth())
1232 damage = me->GetHealth() - 1;
1233 }
1234
1235 void UpdateAI(uint32 diff) override
1236 {
1238 return;
1239
1240 _events.Update(diff);
1241
1242 while (uint32 eventId = _events.ExecuteEvent())
1243 {
1244 switch (eventId)
1245 {
1246 case EVENT_INTRO_A_1:
1248 break;
1249 case EVENT_INTRO_A_2:
1251 break;
1253 sTransportMgr->CreateTransport(GO_ORGRIMS_HAMMER_A, me->GetMap());
1254 break;
1255 case EVENT_INTRO_A_3:
1257 break;
1258 case EVENT_INTRO_A_4:
1260 break;
1261 case EVENT_INTRO_A_5:
1263 break;
1264 case EVENT_INTRO_A_6:
1266 saurfang->AI()->Talk(SAY_SAURFANG_INTRO_A);
1267 break;
1268 case EVENT_INTRO_A_7:
1270 break;
1273 {
1276 }
1277 break;
1278 case EVENT_SUMMON_MAGE:
1281 break;
1282 case EVENT_ADDS:
1287 if (Transport* skybreaker = dynamic_cast<Transport*>(me->GetTransport()))
1288 skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21s);
1289
1291 orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23s);
1292
1295 break;
1298 saurfang->AI()->Talk(SAY_SAURFANG_BOARD);
1299 break;
1302 {
1304 {
1307 }
1308 }
1310 break;
1311 case EVENT_CHECK_MORTAR:
1313 {
1315 {
1318 }
1319 }
1321 break;
1322 case EVENT_CLEAVE:
1325 break;
1326 default:
1327 break;
1328 }
1329 }
1330
1332 {
1333 if (me->isAttackReady())
1334 {
1337 }
1338 }
1339 }
1340
1341 bool CanAIAttack(Unit const* target) const override
1342 {
1344 return false;
1345 return target->HasAura(SPELL_ON_SKYBREAKER_DECK) || target->GetEntry() == NPC_KOR_KRON_REAVER || target->GetEntry() == NPC_KOR_KRON_SERGEANT;
1346 }
1347
1348private:
1355};
1356
1358{
1359 npc_zafod_boombox(Creature* creature) : gunship_npc_AI(creature) { }
1360
1361 void Reset() override
1362 {
1364 }
1365
1366 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override
1367 {
1369 CloseGossipMenuFor(player);
1370 return false;
1371 }
1372
1373 void UpdateAI(uint32 /*diff*/) override
1374 {
1375 UpdateVictim();
1376 }
1377};
1378
1380{
1382 {
1383 me->m_CombatDistance = 80.0f;
1384 _usedDesperateResolve = false;
1385 }
1386
1387 void SetData(uint32 type, uint32 data) override
1388 {
1389 // detach from captain
1390 if (type == ACTION_SET_SLOT)
1391 {
1392 SetSlotInfo(data);
1393
1395
1397
1399 captain->AI()->SetData(ACTION_CLEAR_SLOT, Index);
1400 }
1401 }
1402
1403 void MovementInform(uint32 type, uint32 pointId) override
1404 {
1405 if (type != POINT_MOTION_TYPE)
1406 return;
1407
1408 if (pointId == EVENT_CHARGE_PREPATH && Slot)
1409 {
1411 TransportBase const* myTransport = me->GetTransport();
1412 if (!myTransport)
1413 return;
1414
1416 {
1417 Position globalPosition = destTransport->GetPositionWithOffset(otherTransportPos);
1418
1419 float angle = frand(0, float(M_PI) * 2.0f);
1420 globalPosition.m_positionX += 2.0f * std::cos(angle);
1421 globalPosition.m_positionY += 2.0f * std::sin(angle);
1422
1423 me->SetHomePosition(globalPosition);
1424 me->SetTransportHomePosition(myTransport->GetPositionOffsetTo(globalPosition));
1425 }
1426
1431 me->GetSpellHistory()->AddCooldown(BurningPitchId, 0, std::chrono::seconds(3));
1432
1433 std::list<Player*> players;
1436 Cell::VisitWorldObjects(me, searcher, 200.0f);
1437
1438 players.remove_if([this](Player* player)
1439 {
1440 return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true);
1441 });
1442
1443 if (!players.empty())
1444 {
1445 players.sort(Trinity::ObjectDistanceOrderPred(me));
1446 for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
1447 AddThreat(*itr, 1.0f);
1448
1449 AttackStart(players.front());
1450 }
1451
1453 }
1454 }
1455
1456 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1457 {
1459 return;
1460
1461 if (!me->HealthBelowPctDamaged(25, damage))
1462 return;
1463
1464 _usedDesperateResolve = true;
1466 }
1467
1468 void UpdateAI(uint32 /*diff*/) override
1469 {
1470 if (!SelectVictim())
1471 {
1473 return;
1474 }
1475
1478 }
1479
1480 bool CanAIAttack(Unit const* target) const override
1481 {
1483 uint32 creatureEntry = NPC_IGB_MURADIN_BRONZEBEARD;
1485 {
1487 creatureEntry = NPC_IGB_HIGH_OVERLORD_SAURFANG;
1488 }
1489
1490 return target->HasAura(spellId) || target->GetEntry() == creatureEntry;
1491 }
1492
1494 {
1495 std::list<Player*> players;
1498 Cell::VisitWorldObjects(me, searcher,200.0f );
1499
1500 players.remove_if([this](Player* player)
1501 {
1502 return !me->_IsTargetAcceptable(player) || !me->CanStartAttack(player, true);
1503 });
1504
1505 return !players.empty();
1506 }
1507
1508private:
1510};
1511
1513{
1515
1522
1523 void UpdateAI(uint32 diff) override
1524 {
1525 if (!SelectVictim())
1526 {
1528 return;
1529 }
1530
1531 _events.Update(diff);
1532
1534 return;
1535
1538
1539 while (uint32 eventId = _events.ExecuteEvent())
1540 {
1541 switch (eventId)
1542 {
1543 case EVENT_BLADESTORM:
1546 break;
1550 break;
1551 default:
1552 break;
1553 }
1554 }
1555 }
1556
1557private:
1559};
1560
1562{
1563 public:
1564 npc_gunship_boarding_add() : CreatureScript("npc_gunship_boarding_add") { }
1565
1566 CreatureAI* GetAI(Creature* creature) const override
1567 {
1568 return GetIcecrownCitadelAI<npc_gunship_boarding_addAI>(creature);
1569 }
1570};
1571
1573{
1575 {
1576 creature->m_CombatDistance = 200.0f;
1577 }
1578
1579 void AttackStart(Unit* target) override
1580 {
1581 me->Attack(target, false);
1582 }
1583
1584 void MovementInform(uint32 type, uint32 pointId) override
1585 {
1586 gunship_npc_AI::MovementInform(type, pointId);
1587 if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH)
1589 }
1590
1591 void UpdateAI(uint32 /*diff*/) override
1592 {
1593 if (!SelectVictim())
1594 {
1596 return;
1597 }
1598
1600 }
1601};
1602
1604{
1606 {
1607 creature->m_CombatDistance = 200.0f;
1608 }
1609
1610 void MovementInform(uint32 type, uint32 pointId) override
1611 {
1612 gunship_npc_AI::MovementInform(type, pointId);
1613 if (type == POINT_MOTION_TYPE && pointId == EVENT_CHARGE_PREPATH)
1615 }
1616
1617 void UpdateAI(uint32 /*diff*/) override
1618 {
1619 if (!SelectVictim())
1620 return;
1621
1623 return;
1624
1626 if (me->GetSpellHistory()->HasCooldown(spellId))
1627 return;
1628
1629 DoCastAOE(spellId, true);
1630 me->GetSpellHistory()->AddCooldown(spellId, 0, std::chrono::seconds(9));
1631 }
1632};
1633
1635{
1637 {
1639 }
1640
1641 void EnterEvadeMode(EvadeReason /*why*/) override { }
1642
1643 void MovementInform(uint32 type, uint32 pointId) override
1644 {
1645 if (type != POINT_MOTION_TYPE)
1646 return;
1647
1648 if (pointId == EVENT_CHARGE_PREPATH && Slot)
1649 {
1651 me->SetFacingTo(slots[Index].TargetPosition.GetOrientation());
1652 switch (Index)
1653 {
1654 case SLOT_FREEZE_MAGE:
1656 break;
1657 case SLOT_MAGE_1:
1658 case SLOT_MAGE_2:
1660 break;
1661 default:
1662 break;
1663 }
1664
1666 }
1667 }
1668
1669 void UpdateAI(uint32 /*diff*/) override
1670 {
1671 UpdateVictim();
1672 }
1673
1674 bool CanAIAttack(Unit const* /*target*/) const override
1675 {
1676 return true;
1677 }
1678};
1679
1701{
1702 npc_gunship_cannon(Creature* creature) : PassiveAI(creature) { }
1703
1704 void OnCharmed(bool /*isNew*/) override { }
1705
1706 void PassengerBoarded(Unit* /*passenger*/, int8 /*seat*/, bool apply) override
1707 {
1708 if (!apply)
1709 {
1712 }
1713 }
1714};
1715
1716// 68721 - Rocket Pack
1747
1748// 70348 - Rocket Pack Useable
1750{
1751 bool Load() override
1752 {
1753 return GetOwner()->GetInstanceScript() != nullptr;
1754 }
1755
1756 bool CheckAreaTarget(Unit* target)
1757 {
1759 }
1760
1761 void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1762 {
1763 if (Creature* owner = GetOwner()->ToCreature())
1764 if (Player* target = GetTarget()->ToPlayer())
1765 if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1))
1767 }
1768
1769 void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1770 {
1771 if (Creature* owner = GetOwner()->ToCreature())
1772 if (Player* target = GetTarget()->ToPlayer())
1773 if (target->HasItemCount(ITEM_GOBLIN_ROCKET_PACK, 1))
1775 }
1776
1783};
1784
1785// 70120 - On Skybreaker Deck
1786// 70121 - On Orgrim's Hammer Deck
1788{
1789public:
1794
1795private:
1796 bool Load() override
1797 {
1798 if (InstanceScript* instance = GetOwner()->GetInstanceScript())
1799 _teamInInstance = instance->GetData(DATA_TEAM_IN_INSTANCE);
1800 else
1801 _teamInInstance = 0;
1802 return true;
1803 }
1804
1806 {
1807 return unit->GetTypeId() == TYPEID_PLAYER;
1808 }
1809
1816
1822
1824};
1825
1826// 69470 - Heat Drain
1827// 69487 - Overheat
1841
1842// 69399, 70172 - Cannon Blast
1844{
1845 bool Load() override
1846 {
1847 return GetCaster()->GetTypeId() == TYPEID_UNIT;
1848 }
1849
1851 {
1852 if (GetCaster()->GetPower(POWER_ENERGY) >= 100)
1853 {
1855 if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
1856 if (Unit* passenger = vehicle->GetPassenger(0))
1857 sCreatureTextMgr->SendChat(GetCaster()->ToCreature(), SAY_OVERHEAT, passenger);
1858 }
1859 }
1860
1861 void Register() override
1862 {
1864 }
1865};
1866
1867// 69402, 70175 - Incinerating Blast
1869{
1871 {
1873 }
1874
1876 {
1878 }
1879
1880 void CalculateDamage(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/) const
1881 {
1882 flatMod += _energyLeft * _energyLeft * 8;
1883 }
1884
1891
1893};
1894
1895// 69487 - Overheat
1897{
1898 bool Load() override
1899 {
1900 if (GetAura()->GetType() != UNIT_AURA_TYPE)
1901 return false;
1902 return GetUnitOwner()->IsVehicle();
1903 }
1904
1905 void SendClientControl(bool value)
1906 {
1907 if (Vehicle* vehicle = GetUnitOwner()->GetVehicleKit())
1908 {
1909 if (Unit* passenger = vehicle->GetPassenger(0))
1910 {
1911 if (Player* player = passenger->ToPlayer())
1912 {
1914 data.Guid = GetUnitOwner()->GetGUID();
1915 data.On = value;
1916 player->SendDirectMessage(data.Write());
1917 }
1918 }
1919 }
1920 }
1921
1922 void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1923 {
1924 SendClientControl(false);
1925 }
1926
1927 void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1928 {
1929 SendClientControl(true);
1930 }
1931
1937};
1938
1939// 69705 - Below Zero
1941{
1943 {
1944 if (missInfo != SPELL_MISS_NONE)
1945 return;
1946
1948 }
1949
1954};
1955
1956// 70104 - Teleport to Enemy Ship
1958{
1960 {
1961 WorldLocation const* dest = GetHitDest();
1962 Unit* target = GetHitUnit();
1963 if (!dest || !target || !target->GetTransport())
1964 return;
1965
1967 }
1968
1973};
1974
1975// 70397, 70403 - Burning Pitch
1977{
1978 void FilterTargets(std::list<WorldObject*>& targets)
1979 {
1980 uint32 team = HORDE;
1981 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
1982 team = instance->GetData(DATA_TEAM_IN_INSTANCE);
1983
1984 targets.remove_if([team](WorldObject* target) -> bool
1985 {
1986 if (Transport* transport = dynamic_cast<Transport*>(target->GetTransport()))
1987 return transport->GetEntry() != uint32(team == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A);
1988 return true;
1989 });
1990
1991 if (!targets.empty())
1992 {
1994 targets.clear();
1995 targets.push_back(target);
1996 }
1997 }
1998
2004
2010};
2011
2012// 71335, 71339 - Burning Pitch
2029
2030// 69678, 70609 - Rocket Artillery
2032{
2033 void SelectRandomTarget(std::list<WorldObject*>& targets)
2034 {
2035 if (!targets.empty())
2036 {
2038 targets.clear();
2039 targets.push_back(target);
2040 }
2041 }
2042
2048
2054};
2055
2056// 69679 - Rocket Artillery
2058{
2059 void DamageGunship(SpellEffIndex /*effIndex*/)
2060 {
2061 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
2062 {
2064 args.AddSpellBP0(5000);
2066 }
2067 }
2068
2073};
2074
2075// 67335 - Gunship Fall Teleport
2077{
2078 bool Load() override
2079 {
2080 return GetCaster()->GetInstanceScript() != nullptr;
2081 }
2082
2084 {
2085 if (InstanceScript* instance = target->GetInstanceScript())
2086 target = ObjectAccessor::GetTransport(*GetCaster(), instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE));
2087 }
2088
2089 void RelocateDest(SpellEffIndex /*effIndex*/)
2090 {
2091 if (GetCaster()->GetInstanceScript()->GetData(DATA_TEAM_IN_INSTANCE) == HORDE)
2092 GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 36.0f, 0.0f });
2093 else
2094 GetHitDest()->RelocateOffset({ 0.0f, 0.0f, 21.0f, 0.0f });
2095 }
2096
2102};
2103
2104// 70331 - Check for Players
2106{
2107public:
2112
2113private:
2114 bool Load() override
2115 {
2116 return GetCaster()->GetTypeId() == TYPEID_UNIT;
2117 }
2118
2119 void CountTargets(std::list<WorldObject*>& targets)
2120 {
2121 _playerCount = targets.size();
2122 }
2123
2125 {
2126 if (!_playerCount)
2127 GetCaster()->ToCreature()->AI()->JustDied(nullptr);
2128 }
2129
2131 {
2132 if (GetHitUnit()->GetPositionZ() < GetCaster()->GetPositionZ() - 10.0f)
2134 }
2135
2142
2144};
2145
2146// 72340 - Teleport Players on Victory
2148{
2149 bool Load() override
2150 {
2151 return GetCaster()->GetInstanceScript() != nullptr;
2152 }
2153
2154 void FilterTargets(std::list<WorldObject*>& targets)
2155 {
2157 targets.remove_if([instance](WorldObject* target) -> bool
2158 {
2159 return target->GetTransGUID() != instance->GetGuidData(DATA_ENEMY_GUNSHIP);
2160 });
2161 }
2162
2167};
2168
2169// 71201 - Battle Experience - proc should never happen, handled in script
2171{
2172 bool CheckProc(ProcEventInfo& /*eventInfo*/)
2173 {
2174 return false;
2175 }
2176
2181};
2182
2184{
2185 public:
2186 achievement_im_on_a_boat() : AchievementCriteriaScript("achievement_im_on_a_boat") { }
2187
2188 bool OnCheck(Player* /*source*/, Unit* target) override
2189 {
2190 return target->GetAI() && target->GetAI()->GetData(ACTION_SHIP_VISITS) <= 2;
2191 }
2192};
2193
2195{
2196 // Creatures
2197 new npc_gunship();
2207
2208 // Spells
2226
2227 // Achievements
2229}
#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
Spells
Definition PlayerAI.cpp:32
float frand(float min, float max)
Definition Random.cpp:55
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
#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
@ 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
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_TRIGGER_MISSILE
@ SPELL_EFFECT_TELEPORT_UNITS
@ 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:271
@ UNIT_STATE_CASTING
Definition Unit.h:276
G3D::Vector3 const SaurfangExitPath[]
@ 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 SkybreakerSlotInfo[MAX_SLOTS]
G3D::Vector3 const MuradinExitPath[]
Position const SkybreakerTeleportPortal
Position const OrgrimsHammerTeleportPortal
Position const OrgrimsHammerTeleportExit
SlotInfo const OrgrimsHammerSlotInfo[MAX_SLOTS]
@ SAY_MURADIN_ENTER_ORGRIMMS_HAMMER
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:386
bool _IsTargetAcceptable(Unit const *target) const
bool HasReactState(ReactStates state) const
Definition Creature.h:176
void SetReactState(ReactStates st)
Definition Creature.h:174
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetRegenerateHealth(bool value)
Definition Creature.h:373
float m_CombatDistance
Definition Creature.h:427
Unit * SelectVictim()
void SetTransportHomePosition(float x, float y, float z, float o)
Definition Creature.h:391
CreatureAI * AI() const
Definition Creature.h:228
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
uint32 ExecuteEvent()
Definition EventMap.cpp:77
void Update(uint32 time)
Definition EventMap.h:61
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition EventMap.cpp:40
bool IsInPhase(uint8 phase) const
Definition EventMap.h:222
void SetPhase(uint8 phase)
Definition EventMap.cpp:32
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:3976
bool IsHeroic() const
Definition Map.cpp:3311
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 SummonCreatures(PassengerSlots first, PassengerSlots last)
bool SlotsNeedRefill(PassengerSlots first, PassengerSlots last) const
void ClearSlot(PassengerSlots 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:588
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:61
virtual void Reset()
Definition UnitAI.h:64
virtual void InitializeAI()
Definition UnitAI.cpp:43
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:180
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:89
Definition Unit.h:635
bool IsVehicle() const
Definition Unit.h:754
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:710
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6012
ThreatManager & GetThreatManager()
Definition Unit.h:1078
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11545
void SetPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:10046
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool IsAlive() const
Definition Unit.h:1185
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:998
UnitAI * GetAI() const
Definition Unit.h:668
bool Attack(Unit *victim, bool meleeAttack)
Definition Unit.cpp:5853
uint64 GetHealth() const
Definition Unit.h:788
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:793
Unit * GetVictim() const
Definition Unit.h:726
int32 GetPower(Powers power) const
Definition Unit.cpp:10028
void SetFacingTo(float const ori, bool force=true)
Definition Unit.cpp:13289
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
void RemoveAllAuras()
Definition Unit.cpp:4382
SpellHistory * GetSpellHistory()
Definition Unit.h:1498
void RemoveVehicleKit(bool onRemoveFromWorld=false)
Definition Unit.cpp:12090
bool isAttackReady(WeaponAttackType type=BASE_ATTACK) const
Definition Unit.h:701
void resetAttackTimer(WeaponAttackType type=BASE_ATTACK)
Definition Unit.cpp:665
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3974
bool IsInCombat() const
Definition Unit.h:1058
Map * GetMap() const
Definition Object.h:411
InstanceScript * GetInstanceScript() const
Definition Object.cpp:396
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
TransportBase * GetTransport() const
Definition Object.h:537
virtual ObjectGuid GetTransGUID() const
Definition Object.cpp:3093
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1517
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, bool dont_load=true)
Definition CellImpl.h:191
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