TrinityCore
Loading...
Searching...
No Matches
violet_hold.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 "ScriptMgr.h"
19#include "GameObject.h"
20#include "GameObjectAI.h"
21#include "InstanceScript.h"
22#include "Map.h"
23#include "MotionMaster.h"
24#include "Player.h"
25#include "ScriptedEscortAI.h"
26#include "ScriptedGossip.h"
27#include "SpellAuraEffects.h"
28#include "SpellScript.h"
29#include "TemporarySummon.h"
30#include "violet_hold.h"
31
32/*
33 * TODO:
34 * - add missing trash emotes
35 */
36
59
67
75
83
89
95
101
107
113
119
121{
122 SPELL_DESTROY_DOOR_SEAL = 58040, // > 31326 Corrupt Medivh
123 SPELL_PRISON_DOOR_SEAL_WEAKEN = 58041, // NYI, no effect, maybe > 32613 Medivh's Shield -5%
124 SPELL_DOOR_BROKEN = 58043 // NYI, no effect, maybe > 31327 Medivh Dies!
126
133
135{
137
138 SPELL_ATTACK_VIOLET_HOLD_GUARD = 57936, // NYI, no effect
139
140 // Turned out almost all spells from BM were copied to create Violet Hold. Not only serverside spells and
141 // not only their effects but also attributes and icons. The scripts were also copied, possibly unchanged
142 SPELL_PORTAL_1_READY = 57995, // NYI, effect copied from 'Time Rift 1 Ready'
143 SPELL_PORTAL_2_READY = 57996, // NYI, effect copied from 'Time Rift 2 Ready'
144 SPELL_PORTAL_3_READY = 57997, // NYI, effect copied from 'Time Rift 3 Ready'
145 SPELL_PORTAL_4_READY = 57998, // NYI, effect copied from 'Time Rift 4 Ready'
146 SPELL_PORTAL_5_READY = 57999, // NYI, effect copied from 'Time Rift 1 Ready', only 4 portals in BM
147
148 SPELL_SUMMON_PORTAL = 58002, // NYI, effect copied from 'Summon Time Rift'
149 SPELL_SUMMON_PORTAL_EFFECT_1 = 58003, // NYI, no effect, > Summon Time Rift Effect
150 SPELL_SUMMON_PORTAL_EFFECT_2 = 58004, // NYI, no effect, > Summon Time Rift Effect
151 SPELL_SUMMON_PORTAL_EFFECT_3 = 58005, // NYI, no effect, > Summon Time Rift Effect
152 SPELL_SUMMON_PORTAL_EFFECT_4 = 58006, // NYI, no effect, > Summon Time Rift Effect
153 SPELL_SUMMON_PORTAL_EFFECT_5 = 58007, // NYI, no effect, > Summon Time Rift Effect
154 SPELL_PORTAL_PERIODIC = 58008, // > Time Rift Periodic
155 SPELL_PORTAL_CHANNEL_TRIGGER = 58011, // NYI, effect copied from 'Time Rift Channel Trigger'
156 SPELL_PORTAL_CHANNEL = 58012, // > Time Rift Channel
157 SPELL_CLOSE_PORTAL_TRIGGER = 58014, // NYI, effect copied from 'Close Time Rift Trigger'
158 SPELL_CLOSE_PORTAL_EFFECT = 58018, // NYI, effect copied from 'Close Time Rift Effect'
159 SPELL_PORTAL_READY_PRIMER = 58019, // NYI, effect copied from 'Time Rift Ready Primer'
160
161 SPELL_SUMMON_PORTAL_GUARDIAN = 58028, // NYI, summons 30660
162 SPELL_SUMMON_PORTAL_GUARDIAN_2 = 58029, // NYI, summons 30892
163 SPELL_SUMMON_PORTAL_KEEPER = 58030, // NYI, summons 30695
164 SPELL_SUMMON_PORTAL_KEEPER_2 = 58031, // NYI, summons 30893
165 SPELL_SUMMON_AZURE_BINDER = 58034, // NYI, summons 30663
166 SPELL_SUMMON_AZURE_BINDER_2 = 58086, // NYI, summons 30918
167 SPELL_SUMMON_AZURE_INVADER = 58087, // NYI, summons 30661
168 SPELL_SUMMON_AZURE_INVADER_2 = 58088, // NYI, summons 30961
169 SPELL_SUMMON_AZURE_SPELLBREAKER = 58089, // NYI, summons 30662
170 SPELL_SUMMON_AZURE_SPELLBREAKER_2 = 58090, // NYI, summons 30962
171 SPELL_SUMMON_AZURE_MAGE_SLAYER = 58091, // NYI, summons 30664
172 SPELL_SUMMON_AZURE_MAGE_SLAYER_2 = 58092, // NYI, summons 30963
173 SPELL_SUMMON_VETERAN_MAGE_HUNTER = 58093, // NYI, summons 30665
174
175 SPELL_SUMMON_AZURE_CAPTAIN = 60048, // NYI, summons 30666
176 SPELL_SUMMON_AZURE_STALKER = 60086, // NYI, summons 32191
177 SPELL_SUMMON_AZURE_RAIDER = 60049, // NYI, summons 30668
178 SPELL_SUMMON_AZURE_RAIDER_2 = 60092, // NYI, summons 30668
179 SPELL_SUMMON_AZURE_SORCEROR = 60050, // NYI, summons 30667
180 SPELL_SUMMON_AZURE_SORCEROR_2 = 60093, // NYI, summons 30667
181
185
190
206
208{
209 {1877.670288f, 842.280273f, 43.333591f},
210 {1877.338867f, 834.615356f, 38.762287f},
211 {1872.161011f, 823.854309f, 38.645401f},
212 {1864.860474f, 815.787170f, 38.784843f},
213 {1858.953735f, 810.048950f, 44.008759f},
214 {1843.707153f, 805.807739f, 44.135197f}
215 //{1825.736084f, 807.305847f, 44.363785f}
216};
217
219{
220 {1902.561401f, 853.334656f, 47.106117f},
221 {1895.486084f, 855.376404f, 44.334591f},
222 {1882.805176f, 854.993286f, 43.333591f},
223 {1877.670288f, 842.280273f, 43.333591f},
224 {1877.338867f, 834.615356f, 38.762287f},
225 {1872.161011f, 823.854309f, 38.645401f},
226 {1864.860474f, 815.787170f, 38.784843f},
227 {1858.953735f, 810.048950f, 44.008759f},
228 {1843.707153f, 805.807739f, 44.135197f}
229 //{1825.736084f, 807.305847f, 44.363785f}
230};
231
233{
234 {1929.392212f, 837.614990f, 47.136166f},
235 {1928.290649f, 824.750427f, 45.474411f},
236 {1915.544922f, 826.919373f, 38.642811f},
237 {1900.933960f, 818.855652f, 38.801647f},
238 {1886.810547f, 813.536621f, 38.490490f},
239 {1869.079712f, 808.701538f, 38.689003f},
240 {1860.843384f, 806.645020f, 44.008789f},
241 {1843.707153f, 805.807739f, 44.135197f}
242 //{1825.736084f, 807.305847f, 44.363785f}
243};
244
246{
247 {1934.049438f, 815.778503f, 52.408699f},
248 {1928.290649f, 824.750427f, 45.474411f},
249 {1915.544922f, 826.919373f, 38.642811f},
250 {1900.933960f, 818.855652f, 38.801647f},
251 {1886.810547f, 813.536621f, 38.490490f},
252 {1869.079712f, 808.701538f, 38.689003f},
253 {1860.843384f, 806.645020f, 44.008789f},
254 {1843.707153f, 805.807739f, 44.135197f}
255 //{1825.736084f, 807.305847f, 44.363785f}
256};
257
259{
260 {1921.658447f, 761.657043f, 50.866741f},
261 {1910.559814f, 755.780457f, 47.701447f},
262 {1896.664673f, 752.920898f, 47.667004f},
263 {1887.398804f, 763.633240f, 47.666851f},
264 {1879.020386f, 775.396973f, 38.705990f},
265 {1872.439087f, 782.568604f, 38.808292f},
266 {1863.573364f, 791.173584f, 38.743660f},
267 {1857.811890f, 796.765564f, 43.950329f},
268 {1845.577759f, 800.681152f, 44.104248f}
269 //{1827.100342f, 801.605957f, 44.363358f}
270};
271
273{
274 {1887.398804f, 763.633240f, 47.666851f},
275 {1879.020386f, 775.396973f, 38.705990f},
276 {1872.439087f, 782.568604f, 38.808292f},
277 {1863.573364f, 791.173584f, 38.743660f},
278 {1857.811890f, 796.765564f, 43.950329f},
279 {1845.577759f, 800.681152f, 44.104248f}
280 //{1827.100342f, 801.605957f, 44.363358f}
281};
282
284{
285 {1888.861084f, 805.074768f, 38.375790f},
286 {1869.793823f, 804.135804f, 38.647018f},
287 {1861.541504f, 804.149780f, 43.968292f},
288 {1843.567017f, 804.288208f, 44.139091f}
289 //{1826.889648f, 803.929993f, 44.363239f}
290};
291
293{
294 { 1843.567017f, 804.288208f, 44.139091f }
295};
296
297Position const SaboteurMoraggPath[] = // sniff
298{
299 { 1886.251f, 803.0743f, 38.42326f },
300 { 1885.71f, 799.8929f, 38.37241f },
301 { 1889.505f, 762.3288f, 47.66684f },
302 { 1894.542f, 742.1829f, 47.66684f },
303 { 1894.603f, 739.9231f, 47.66684f },
304};
305
306Position const SaboteurErekemPath[] = // sniff
307{
308 { 1886.251f, 803.0743f, 38.42326f },
309 { 1881.047f, 829.6866f, 38.64856f },
310 { 1877.585f, 844.6685f, 38.49014f },
311 { 1876.085f, 851.6685f, 42.99014f },
312 { 1873.747f, 864.1373f, 43.33349f }
313};
314
316{
317 { 1886.251f, 803.0743f, 38.42326f },
318 { 1888.672f, 801.2348f, 38.42305f },
319 { 1901.987f, 793.3254f, 38.65126f }
320};
321
323{
324 { 1886.251f, 803.0743f, 38.42326f },
325 { 1867.925f, 778.8035f, 38.64702f },
326 { 1853.304f, 759.0161f, 38.65761f }
327};
328
329Position const SaboteurXevozzPath[] = // sniff
330{
331 { 1886.251f, 803.0743f, 38.42326f },
332 { 1889.096f, 810.0487f, 38.43871f },
333 { 1896.547f, 823.5473f, 38.72863f },
334 { 1906.666f, 842.3111f, 38.63351f }
335};
336
338{
339 { 1886.251f, 803.0743f, 38.42326f },
340 { 1889.69f, 807.0032f, 38.39914f },
341 { 1906.91f, 818.2574f, 38.86596f },
342 { 1929.03f, 824.2713f, 46.09165f },
343 { 1928.441f, 842.8891f, 47.15078f },
344 { 1927.454f, 851.6091f, 47.19094f },
345 { 1927.947f, 852.2986f, 47.19637f }
346};
347
348Position const SinclariPositions[] = // sniff
349{
350 { 1829.142f, 798.219f, 44.36212f, 0.122173f }, // 0 - Crystal
351 { 1820.12f, 803.916f, 44.36466f, 0.0f }, // 1 - Outside
352 { 1816.185f, 804.0629f, 44.44799f, 3.176499f }, // 2 - Second Spawn Point
353 { 1827.886f, 804.0555f, 44.36467f, 0.0f } // 3 - Outro
354};
355
356Position const GuardsMovePosition = { 1802.099f, 803.7724f, 44.36466f, 0.0f }; // sniff
357
358// 30658 - Lieutenant Sinclari
360{
361 npc_sinclari_vh(Creature* creature) : ScriptedAI(creature), _summons(creature)
362 {
363 _instance = creature->GetInstanceScript();
364 }
365
366 void Reset() override
367 {
369 for (uint8 i = 0; i < PortalIntroCount; ++i)
371 summon->AI()->SetData(DATA_PORTAL_LOCATION, i);
372
374
375 std::list<Creature*> guardList;
377 for (Creature* guard : guardList)
378 {
379 guard->Respawn(true);
380 guard->SetVisible(true);
381 guard->SetReactState(REACT_AGGRESSIVE);
382 guard->AI()->EnterEvadeMode();
383 }
384 }
385
386 bool OnGossipHello(Player* player) override
387 {
388 // override default gossip
390 {
391 case IN_PROGRESS:
393 player->SendPreparedGossip(me);
394 return true;
395 case DONE:
396 return true; // NYI
397 case NOT_STARTED:
398 case FAIL:
399 default:
400 break;
401 }
402
403 // load default gossip
404 return false;
405 }
406
407 bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
408 {
409 if (menuId == GOSSIP_MENU_START_ENCOUNTER && gossipListId == 0)
410 {
415 }
416 else if (menuId == GOSSIP_MENU_SEND_ME_IN && gossipListId == 0)
417 {
418 me->CastSpell(player, SPELL_TELEPORT_PLAYER, true);
420 }
421 return false;
422 }
423
424 void DoAction(int32 actionId) override
425 {
426 if (actionId == ACTION_SINCLARI_OUTRO)
428 }
429
430 void UpdateAI(uint32 diff) override
431 {
432 _scheduler.Update(diff);
433
434 if (!UpdateVictim())
435 return;
436
438 }
439
441 {
442 _scheduler.Schedule(1s, [this](TaskContext task)
443 {
444 switch (task.GetRepeatCounter())
445 {
446 case 0:
447 me->SetWalk(true);
448 me->GetMotionMaster()->MovePoint(0, SinclariPositions[0]);
449 task.Repeat(1s);
450 break;
451 case 1:
452 me->HandleEmoteCommand(EMOTE_ONESHOT_USE_STANDING);
453 me->GetMap()->SummonCreature(NPC_DEFENSE_SYSTEM, DefenseSystemLocation);
454 task.Repeat(3s);
455 break;
456 case 2:
457 me->SetFacingTo(SinclariPositions[0].GetOrientation());
458 Talk(SAY_SINCLARI_INTRO_1);
459
460 task.Schedule(1s, [this](TaskContext /*task*/)
461 {
462 std::list<Creature*> guardList;
463 me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f);
464 for (Creature* guard : guardList)
465 {
466 if (!guard->IsAlive())
467 continue;
468 guard->SetReactState(REACT_PASSIVE);
469 guard->SetWalk(false);
470 guard->GetMotionMaster()->MovePoint(0, GuardsMovePosition);
471 }
472 });
473
474 task.Repeat(2s);
475 break;
476 case 3:
479 task.Repeat(5s);
480 break;
481 case 4:
482 me->SetFacingTo(SinclariPositions[1].GetOrientation());
483
484 task.Schedule(1s, [this](TaskContext /*task*/)
485 {
486 std::list<Creature*> guardList;
488 for (Creature* guard : guardList)
489 guard->SetVisible(false);
490 });
491
492 task.Repeat(6s);
493 break;
494 case 5:
496 task.Repeat(4s);
497 break;
498 case 6:
500 task.Repeat(1s);
501 break;
502 case 7:
504 {
505 mainDoor->SetGoState(GO_STATE_READY);
506 mainDoor->SetFlag(GO_FLAG_LOCKED);
507 }
508 task.Repeat(5s);
509 break;
510 case 8:
512 task.Repeat(1s);
513 break;
514 case 9:
515 // We should teleport inside if event is in progress with GOSSIP_MENU_SEND_ME_IN
517 break;
518 default:
519 break;
520 }
521 });
522 }
523
525 {
526 _scheduler.Schedule(4s, [this](TaskContext task)
527 {
529 me->GetMotionMaster()->MovePoint(0, SinclariPositions[3]);
530
531 task.Schedule(10s, [this](TaskContext /*task*/)
532 {
533 me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
534 });
535 });
536 }
537
538 void JustSummoned(Creature* summon) override
539 {
541 _summons.Summon(summon);
542 }
543
544 void SummonedCreatureDespawn(Creature* summon) override
545 {
546 _summons.Despawn(summon);
548 }
549
550private:
553
555};
556
557// 31079 - Azure Saboteur
559{
561 {
562 _instance = creature->GetInstanceScript();
563
566 else
568 }
569
570 template <size_t N>
571 void StartSmoothPath(Position const (&path)[N])
572 {
573 me->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, &path[0], N, false);
574 }
575
577 {
578 switch (_bossId)
579 {
580 case DATA_MORAGG:
582 break;
583 case DATA_EREKEM:
585 break;
586 case DATA_ICHORON:
588 break;
589 case DATA_LAVANTHOR:
591 break;
592 case DATA_XEVOZZ:
594 break;
595 case DATA_ZURAMAT:
597 break;
598 }
599 }
600
601 void Reset() override
602 {
604 _scheduler.Schedule(2s, [this](TaskContext /*task*/)
605 {
607 });
608 }
609
610 void MovementInform(uint32 type, uint32 pointId) override
611 {
612 if (type == EFFECT_MOTION_TYPE && pointId == POINT_INTRO)
613 {
614 _scheduler.Schedule(0s, [this](TaskContext task)
615 {
617
618 if (task.GetRepeatCounter() < 2)
619 task.Repeat(1s);
620 else
621 {
622 task.Schedule(2s, [this](TaskContext /*task*/)
623 {
627 });
628 }
629 });
630 }
631 }
632
633 void UpdateAI(uint32 diff) override
634 {
635 _scheduler.Update(diff);
636 }
637
638private:
641
643};
644
646{
652
653 void InitializeAI() override
654 {
657 }
658
659 void SetData(uint32 type, uint32 data) override
660 {
661 if (type == DATA_PORTAL_LOCATION)
662 _portalLocation = uint8(data);
663 }
664
665 void MoveInLineOfSight(Unit* /*who*/) override { }
666
667 void JustEngagedWith(Unit* /*who*/) override { }
668
669 void JustSummoned(Creature* summon) override
670 {
671 _summons.Summon(summon);
673 }
674
675 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
676 {
677 _summons.Despawn(summon);
678 }
679
680 virtual void ScheduleTasks() { }
681
682 void UpdateAI(uint32 diff) override
683 {
684 _scheduler.Update(diff);
685 }
686
687protected:
692};
693
694// 30679 - Teleportation Portal
696{
700
706
707 void SetData(uint32 type, uint32 data) override
708 {
710
711 if (type == DATA_PORTAL_PERIODIC_TICK)
712 {
713 if (data == 1)
714 {
716 if (Creature* portalKeeper = DoSummon(entry, me, 2.0f, 0s, TEMPSUMMON_DEAD_DESPAWN))
717 me->CastSpell(portalKeeper, SPELL_PORTAL_CHANNEL, false);
718
719 if (Creature* sinclariTrigger = _instance->GetCreature(DATA_SINCLARI_TRIGGER))
720 {
721 if (entry == NPC_PORTAL_GUARDIAN)
722 sinclariTrigger->AI()->Talk(SAY_SINCLARI_PORTAL_GUARDIAN);
723 else if (entry == NPC_PORTAL_KEEPER)
724 sinclariTrigger->AI()->Talk(SAY_SINCLARI_PORTAL_KEEPER);
725 }
726 }
727 else
728 {
729 uint8 k = _instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4;
730 while (k--)
731 {
733 DoSummon(entry, me, 2.0f, 20s, TEMPSUMMON_DEAD_DESPAWN);
734 }
735 }
736 }
737 }
738
739 void SummonedCreatureDies(Creature* summon, Unit* killer) override
740 {
742
743 if (summon->GetEntry() == NPC_PORTAL_GUARDIAN || summon->GetEntry() == NPC_PORTAL_KEEPER)
744 {
747 }
748 }
749};
750
751// 32174 - Teleportation Portal (Elite)
753{
757
758 void ScheduleTasks() override
759 {
760 _scheduler.Schedule(Seconds(15), [this](TaskContext task)
761 {
762 uint8 k = _instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4;
763 while (k--)
764 {
766 DoSummon(entry, me, 2.0f, 20s, TEMPSUMMON_DEAD_DESPAWN);
767 }
768
769 if (Creature* sinclariTrigger = _instance->GetCreature(DATA_SINCLARI_TRIGGER))
770 sinclariTrigger->AI()->Talk(SAY_SINCLARI_ELITE_SQUAD);
771
772 task.Schedule(1s, [this](TaskContext /*task*/)
773 {
774 me->SetVisible(false);
775 });
776 });
777 }
778
789};
790
791// 31011 - Teleportation Portal (Intro)
793{
797
798 void ScheduleTasks() override
799 {
801 return;
802
803 _scheduler.Schedule(15s, [this](TaskContext task)
804 {
805 // Limit the number of current summons
806 if (_summons.size() < 3)
807 {
808 uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_BINDER_1);
809 DoSummon(entry, me, 2.0f, 20s, TEMPSUMMON_DEAD_DESPAWN);
810 }
811
812 task.Repeat();
813 });
814 }
815};
816
818{
819 violet_hold_trashAI(Creature* creature) : EscortAI(creature)
820 {
821 _instance = creature->GetInstanceScript();
822
823 _lastWaypointId = 0;
824
825 SetDespawnAtEnd(false);
826
828 {
830 });
831 }
832
833 void Reset() override
834 {
837 }
838
839 template <size_t N>
841 {
842 _lastWaypointId = N - 1;
843 return &path[0];
844 }
845
846 void SetData(uint32 type, uint32 data) override
847 {
848 if (type == DATA_PORTAL_LOCATION)
849 {
850 Position const* path = nullptr;
851
852 switch (data)
853 {
854 case 0:
856 break;
857 case 7:
858 switch (urand(0, 1))
859 {
860 case 0:
862 break;
863 case 1:
865 break;
866 }
867 break;
868 case 2:
870 break;
871 case 6:
873 break;
874 case 1:
876 break;
877 case 5:
879 break;
880 default:
882 break;
883 }
884
885 if (path)
886 {
887 for (uint32 i = 0; i <= _lastWaypointId; i++)
888 AddWaypoint(i, path[i].GetPositionX() + irand(-1, 1), path[i].GetPositionY() + irand(-1, 1), path[i].GetPositionZ(), 0, 0s, true);
889 me->SetHomePosition(path[_lastWaypointId].GetPositionX(), path[_lastWaypointId].GetPositionY(), path[_lastWaypointId].GetPositionZ(), float(M_PI));
890 }
891
892 Start(true);
893 }
894 }
895
896 void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
897 {
898 if (waypointId == _lastWaypointId)
899 {
902 _scheduler.Schedule(2s, [this](TaskContext destroyDoorCheck)
903 {
906 destroyDoorCheck.Repeat();
907 });
908 }
909 }
910
911 void JustEngagedWith(Unit* who) override
912 {
914 return;
915
918 }
919
920 void UpdateEscortAI(uint32 diff) override
921 {
923 me->CastStop();
924
925 if (!UpdateVictim())
926 return;
927
928 _scheduler.Update(diff,
929 std::bind(&EscortAI::DoMeleeAttackIfReady, this));
930 }
931
932 virtual void ScheduledTasks() { }
933
934protected:
937
939};
940
941// 30661 - Azure Invader
942// 30961 - Azure Invader
944{
946
947 void ScheduledTasks() override
948 {
950 {
951 _scheduler.Schedule(5s, [this](TaskContext task)
952 {
954 task.Repeat();
955 });
956
957 _scheduler.Schedule(4s, [this](TaskContext task)
958 {
960 task.Repeat();
961 });
962 }
963 else if (me->GetEntry() == NPC_AZURE_INVADER_2)
964 {
965 _scheduler.Schedule(5s, [this](TaskContext task)
966 {
968 task.Repeat();
969 });
970
971 _scheduler.Schedule(4s, [this](TaskContext task)
972 {
974 task.Repeat(8s, 10s);
975 });
976 }
977 }
978};
979
980// 30663 - Azure Binder
981// 30918 - Azure Binder
983{
985
986 void ScheduledTasks() override
987 {
989 {
990 _scheduler.Schedule(5s, [this](TaskContext task)
991 {
993 task.Repeat();
994 });
995
996 _scheduler.Schedule(4s, [this](TaskContext task)
997 {
998 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
1000 task.Repeat(6s);
1001 });
1002 }
1003 else if (me->GetEntry() == NPC_AZURE_BINDER_2)
1004 {
1005 _scheduler.Schedule(5s, [this](TaskContext task)
1006 {
1008 task.Repeat();
1009 });
1010
1011 _scheduler.Schedule(4s, [this](TaskContext task)
1012 {
1013 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
1014 DoCast(target, SPELL_FROSTBOLT);
1015 task.Repeat(6s);
1016 });
1017 }
1018 }
1019};
1020
1021// 30664 - Azure Mage Slayer
1022// 30963 - Azure Mage Slayer
1024{
1026
1027 void ScheduledTasks() override
1028 {
1030 {
1031 _scheduler.Schedule(5s, [this](TaskContext task)
1032 {
1034 task.Repeat(14s);
1035 });
1036 }
1037 else if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2)
1038 {
1039 _scheduler.Schedule(5s, [this](TaskContext task)
1040 {
1041 // wrong spellid?
1042 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
1043 DoCast(target, SPELL_SPELL_LOCK);
1044 task.Repeat(9s);
1045 });
1046 }
1047 }
1048};
1049
1050// 30668 - Azure Raider
1052{
1054
1055 void ScheduledTasks() override
1056 {
1057 _scheduler.Schedule(5s, [this](TaskContext task)
1058 {
1060 task.Repeat();
1061 });
1062
1063 _scheduler.Schedule(8s, [this](TaskContext task)
1064 {
1066 task.Repeat(10s, 15s);
1067 });
1068 }
1069};
1070
1071// 32191 - Azure Stalker
1073{
1075
1076 void ScheduledTasks() override
1077 {
1078 _scheduler.Schedule(8s, [this](TaskContext task)
1079 {
1080 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f))
1082
1083 task.Schedule(1300ms, [this](TaskContext /*task*/)
1084 {
1085 if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 5.0f))
1086 DoCast(target, SPELL_BACKSTAB);
1087 });
1088
1089 task.Repeat();
1090 });
1091 }
1092};
1093
1094// 30662 - Azure Spellbreaker
1095// 30962 - Azure Spellbreaker
1097{
1099
1100 void ScheduledTasks() override
1101 {
1103 {
1104 _scheduler.Schedule(5s, [this](TaskContext task)
1105 {
1106 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
1107 DoCast(target, SPELL_ARCANE_BLAST);
1108 task.Repeat(6s);
1109 });
1110
1111 _scheduler.Schedule(4s, [this](TaskContext task)
1112 {
1113 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
1114 DoCast(target, SPELL_SLOW);
1115 task.Repeat(5s);
1116 });
1117 }
1118 else if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2)
1119 {
1120 _scheduler.Schedule(5s, [this](TaskContext task)
1121 {
1122 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f))
1123 DoCast(target, SPELL_CHAINS_OF_ICE);
1124 task.Repeat(7s);
1125 });
1126
1127 _scheduler.Schedule(4s, [this](TaskContext task)
1128 {
1130 task.Repeat(5s);
1131 });
1132 }
1133 }
1134};
1135
1136// 30666 - Azure Captain
1138{
1140
1141 void ScheduledTasks() override
1142 {
1143 _scheduler.Schedule(5s, [this](TaskContext task)
1144 {
1146 task.Repeat();
1147 });
1148
1149 _scheduler.Schedule(8s, [this](TaskContext task)
1150 {
1152 task.Repeat();
1153 });
1154 }
1155};
1156
1157// 30667 - Azure Sorceror
1159{
1161
1162 void ScheduledTasks() override
1163 {
1164 _scheduler.Schedule(4s, [this](TaskContext task)
1165 {
1166 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 35.0f))
1167 DoCast(target, SPELL_ARCANE_STREAM);
1168 task.Repeat(5s, 10s);
1169 });
1170
1171 _scheduler.Schedule(0s, [this](TaskContext task)
1172 {
1174 task.Repeat(2s, 6s);
1175 });
1176 }
1177};
1178
1179// 30837 - Defense System
1181{
1183
1184 void Reset() override
1185 {
1187 me->DespawnOrUnsummon(7s);
1188 }
1189
1191 {
1192 _scheduler.Schedule(4s, [this](TaskContext task)
1193 {
1196 if (task.GetRepeatCounter() == 2)
1198 else
1199 task.Repeat(1s);
1200 });
1201 }
1202
1203 void UpdateAI(uint32 diff) override
1204 {
1205 _scheduler.Update(diff);
1206 }
1207
1208private:
1210};
1211
1212// 193611 - Activation Crystal
1214{
1216
1217 bool OnGossipHello(Player* player) override
1218 {
1219 player->CastSpell(player, SPELL_CRYSTAL_ACTIVATION, true);
1220 return false;
1221 }
1222};
1223
1224// 58040 - Destroy Door Seal
1226{
1228
1229 bool Load() override
1230 {
1232 return _instance != nullptr;
1233 }
1234
1235 void PeriodicTick(AuraEffect const* /*aurEff*/)
1236 {
1238 if (uint32 integrity = _instance->GetData(DATA_DOOR_INTEGRITY))
1239 _instance->SetData(DATA_DOOR_INTEGRITY, integrity - 1);
1240 }
1241
1246
1247private:
1249};
1250
1251// 58008 - Portal Periodic
1268
1269// 62138 - Teleport to Inside Violet Hold
1271{
1273
1274 bool Validate(SpellInfo const* /*spellInfo*/) override
1275 {
1277 }
1278
1279 void HandleScript(SpellEffIndex /*effIndex*/)
1280 {
1281 if (Unit* target = GetHitUnit())
1282 target->CastSpell(target, SPELL_TELEPORT_PLAYER_EFFECT, true);
1283 }
1284
1289};
1290
#define M_PI
Definition Common.h:72
First const & RAND(First const &first, Second const &second, Rest const &... rest)
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
@ IN_PROGRESS
@ FAIL
@ DONE
@ SPECIAL
@ NOT_STARTED
@ EFFECT_MOTION_TYPE
@ TEMPSUMMON_DEAD_DESPAWN
@ TEMPSUMMON_MANUAL_DESPAWN
int32 irand(int32 min, int32 max)
Definition Random.cpp:35
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_SCRIPT_EFFECT
@ EMOTE_ONESHOT_TALK_NO_SHEATHE
@ GO_FLAG_LOCKED
@ GO_STATE_READY
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
#define SpellEffectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
@ REACT_DEFENSIVE
@ REACT_AGGRESSIVE
@ UNIT_NPC_FLAG_GOSSIP
@ UNIT_STATE_CASTING
Definition Unit.h:235
uint32 GetTickNumber() const
void PreventDefaultAction()
HookList< EffectPeriodicHandler > OnEffectPeriodic
Unit * GetTarget() const
Unit * GetUnitOwner() const
virtual void JustEngagedWith(Unit *)
Definition CreatureAI.h:127
virtual void JustSummoned(Creature *)
Definition CreatureAI.h:136
virtual void SummonedCreatureDespawn(Creature *)
Definition CreatureAI.h:139
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
Creature * DoSummon(uint32 entry, Position const &pos, Milliseconds despawnTime=30s, TempSummonType summonType=TEMPSUMMON_CORPSE_TIMED_DESPAWN)
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:293
bool HasReactState(ReactStates state) const
Definition Creature.h:121
void SetReactState(ReactStates st)
Definition Creature.h:119
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureAI * AI() const
Definition Creature.h:154
Creature * GetCreature(uint32 type)
GameObject * GetGameObject(uint32 type)
void MoveSmoothPath(uint32 pointId, Position const *pathPoints, size_t pathSize, bool walk)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={})
uint32 GetEntry() const
Definition Object.h:81
void SendCloseGossip()
void SendPreparedGossip(WorldObject *source)
Definition Player.cpp:14052
void PrepareGossipMenu(WorldObject *source, uint32 menuId=0, bool showQuests=false)
Definition Player.cpp:13886
PlayerMenu * PlayerTalkClass
Definition Player.h:1969
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
bool empty() const
void Despawn(Creature const *summon)
void Summon(Creature const *summon)
size_type size() const
TaskContext & Repeat(std::chrono::duration< _Rep, _Period > const &duration)
TaskScheduler::repeated_t GetRepeatCounter() const
Returns the repeat counter which increases every time the task is repeated.
TaskContext & Schedule(std::chrono::duration< _Rep, _Period > const &time, TaskScheduler::task_handler_t const &task)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
TaskScheduler & SetValidator(P &&predicate)
Sets a validator which is asked if tasks are allowed to be executed.
virtual void SetData(uint32, uint32)
Definition UnitAI.h:156
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
virtual void InitializeAI()
Definition UnitAI.cpp:36
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
void CastStop(uint32 except_spellid=0)
Definition Unit.cpp:988
void SetVisible(bool x)
Definition Unit.cpp:8513
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1098
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:1097
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13250
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:3153
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:55
virtual void SetData(uint32, uint32)
Definition ZoneScript.h:56
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
void PeriodicTick(AuraEffect const *)
PrepareAuraScript(spell_violet_hold_destroy_door_seal)
PrepareAuraScript(spell_violet_hold_portal_periodic)
void PeriodicTick(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_violet_hold_teleport_player)
@ DATA_WAVE_COUNT
Position const PortalIntroPositions[PortalIntroPositionsSize]
void Start(bool isActiveAttacker=true, ObjectGuid playerGUID=ObjectGuid::Empty, Quest const *quest=nullptr, bool instantRespawn=false, bool canLoopPath=false)
void AddWaypoint(uint32 id, float x, float y, float z, bool run)
void SetDespawnAtEnd(bool despawn)
go_activation_crystal(GameObject *go)
bool OnGossipHello(Player *player) override
npc_azure_binder(Creature *creature)
void ScheduledTasks() override
void ScheduledTasks() override
npc_azure_captain(Creature *creature)
npc_azure_invader(Creature *creature)
void ScheduledTasks() override
void ScheduledTasks() override
npc_azure_mage_slayer(Creature *creature)
npc_azure_raider(Creature *creature)
void ScheduledTasks() override
npc_azure_saboteur(Creature *creature)
void StartSmoothPath(Position const (&path)[N])
InstanceScript * _instance
void Reset() override
void MovementInform(uint32 type, uint32 pointId) override
TaskScheduler _scheduler
void UpdateAI(uint32 diff) override
void ScheduledTasks() override
npc_azure_sorceror(Creature *creature)
npc_azure_spellbreaker(Creature *creature)
void ScheduledTasks() override
void ScheduledTasks() override
npc_azure_stalker(Creature *creature)
SummonList _summons
bool OnGossipHello(Player *player) override
void JustSummoned(Creature *summon) override
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
TaskScheduler _scheduler
InstanceScript * _instance
void DoAction(int32 actionId) override
npc_sinclari_vh(Creature *creature)
void Reset() override
void UpdateAI(uint32 diff) override
void SummonedCreatureDespawn(Creature *summon) override
void UpdateAI(uint32 diff) override
npc_violet_hold_defense_system(Creature *creature)
void SummonedCreatureDies(Creature *summon, Unit *) override
npc_violet_hold_teleportation_portal_commonAI(Creature *creature)
void JustSummoned(Creature *summon) override
void SetData(uint32 type, uint32 data) override
npc_violet_hold_teleportation_portal_elite(Creature *creature)
void SummonedCreatureDies(Creature *summon, Unit *killer) override
npc_violet_hold_teleportation_portal_intro(Creature *creature)
void SummonedCreatureDies(Creature *summon, Unit *killer) override
npc_violet_hold_teleportation_portal(Creature *creature)
void SetData(uint32 type, uint32 data) override
void WaypointReached(uint32 waypointId, uint32) override
void UpdateEscortAI(uint32 diff) override
Position const * GetPathAndInitLastWaypointFrom(Position const (&path)[N])
void JustEngagedWith(Unit *who) override
virtual void ScheduledTasks()
violet_hold_trashAI(Creature *creature)
void Reset() override
InstanceScript * _instance
TaskScheduler _scheduler
void SetData(uint32 type, uint32 data) override
DefenseSystemSpells
@ SPELL_ARCANE_LIGHTNING_DUMMY
@ SPELL_ARCANE_LIGHTNING_DAMAGE
@ SPELL_ARCANE_LIGHTNING_INSTAKILL
void AddSC_violet_hold()
Position const SaboteurLavanthorPath[]
@ DATA_PORTAL_PERIODIC_TICK
AzureSorcerorSpells
@ SPELL_ARCANE_STREAM
@ SPELL_MANA_DETONATION
AzureSellbreakerSpells
@ SPELL_SLOW
@ SPELL_CONE_OF_COLD
@ SPELL_CHAINS_OF_ICE
@ SPELL_ARCANE_BLAST
Sinclari
@ SAY_SINCLARI_OUTRO
@ SAY_SINCLARI_INTRO_2
@ SAY_SINCLARI_ELITE_SQUAD
@ SAY_SINCLARI_PORTAL_KEEPER
@ GOSSIP_MENU_SEND_ME_IN
@ SAY_SINCLARI_PORTAL_GUARDIAN
@ SAY_SINCLARI_INTRO_1
@ GOSSIP_MENU_START_ENCOUNTER
Position const FourthPortalWPs[]
Position const SaboteurErekemPath[]
MiscSpells
@ SPELL_PORTAL_CHANNEL_TRIGGER
@ SPELL_SUMMON_AZURE_CAPTAIN
@ SPELL_SUMMON_PORTAL_EFFECT_2
@ SPELL_SUMMON_AZURE_INVADER
@ SPELL_SUMMON_AZURE_SORCEROR_2
@ SPELL_SUMMON_PORTAL_KEEPER
@ SPELL_TELEPORT_PLAYER_EFFECT
@ SPELL_SUMMON_PORTAL_GUARDIAN_2
@ SPELL_SUMMON_AZURE_INVADER_2
@ SPELL_SUMMON_AZURE_SPELLBREAKER_2
@ SPELL_SUMMON_AZURE_MAGE_SLAYER_2
@ SPELL_SUMMON_PORTAL_KEEPER_2
@ SPELL_PORTAL_READY_PRIMER
@ SPELL_SUMMON_AZURE_SPELLBREAKER
@ SPELL_SUMMON_VETERAN_MAGE_HUNTER
@ SPELL_SUMMON_AZURE_MAGE_SLAYER
@ SPELL_SUMMON_PORTAL_EFFECT_1
@ SPELL_PORTAL_CHANNEL
@ SPELL_CRYSTAL_ACTIVATION
@ SPELL_SUMMON_PORTAL
@ SPELL_PORTAL_4_READY
@ SPELL_SUMMON_AZURE_BINDER_2
@ SPELL_TELEPORT_PLAYER
@ SPELL_PORTAL_1_READY
@ SPELL_SUMMON_PORTAL_GUARDIAN
@ SPELL_SUMMON_PORTAL_EFFECT_4
@ SPELL_SUMMON_AZURE_STALKER
@ SPELL_PORTAL_PERIODIC
@ SPELL_CLOSE_PORTAL_TRIGGER
@ SPELL_SUMMON_PORTAL_EFFECT_5
@ SPELL_PORTAL_5_READY
@ SPELL_PORTAL_2_READY
@ SPELL_SUMMON_AZURE_SORCEROR
@ SPELL_SUMMON_AZURE_RAIDER_2
@ SPELL_SUMMON_AZURE_BINDER
@ SPELL_SUMMON_AZURE_RAIDER
@ SPELL_PORTAL_3_READY
@ SPELL_ATTACK_VIOLET_HOLD_GUARD
@ SPELL_CLOSE_PORTAL_EFFECT
@ SPELL_SUMMON_PORTAL_EFFECT_3
Position const SecondPortalSecondWPs[]
Position const SecondPortalFirstWPs[]
AzureRaiderSpells
@ SPELL_CONCUSSION_BLOW
@ SPELL_MAGIC_REFLECTION
PortalCreatureIds
@ NPC_AZURE_STALKER_1
@ NPC_AZURE_SPELLBREAKER_2
@ NPC_AZURE_BINDER_2
@ NPC_VETERAN_MAGE_HUNTER
@ NPC_AZURE_BINDER_1
@ NPC_AZURE_MAGE_SLAYER_2
@ NPC_AZURE_RAIDER_1
@ NPC_AZURE_MAGE_SLAYER_1
@ NPC_AZURE_INVADER_3
@ NPC_AZURE_SORCEROR_1
@ NPC_AZURE_INVADER_2
@ NPC_AZURE_SPELLBREAKER_1
@ NPC_AZURE_SPELLBREAKER_3
@ NPC_AZURE_BINDER_3
@ NPC_AZURE_RAIDER_2
@ NPC_AZURE_MAGE_SLAYER_3
@ NPC_AZURE_INVADER_1
@ NPC_AZURE_CAPTAIN_1
AzureSaboteurSpells
@ SPELL_TELEPORT_VISUAL
@ SPELL_SHIELD_DISRUPTION
AzureStalkerSpells
@ SPELL_BACKSTAB
@ SPELL_TACTICAL_BLINK
TrashDoorSpell
@ SPELL_PRISON_DOOR_SEAL_WEAKEN
@ SPELL_DESTROY_DOOR_SEAL
@ SPELL_DOOR_BROKEN
Position const SaboteurIchoronPath[]
Position const SixthPortalWPs[]
Position const SinclariPositions[]
Position const SaboteurMoraggPath[]
Position const FirstPortalWPs[]
Position const DefaultPortalWPs[]
AzureMageSlayerSpells
@ SPELL_SPELL_LOCK
@ SPELL_ARCANE_EMPOWERMENT
AzureBinderSpells
@ SPELL_FROSTBOLT
@ SPELL_ARCANE_BARRAGE
@ SPELL_ARCANE_EXPLOSION
@ SPELL_FROST_NOVA
Position const FifthPortalWPs[]
Position const ThirdPortalWPs[]
Position const SaboteurZuramatPath[]
AzureInvaderSpells
@ SPELL_CLEAVE
@ SPELL_SUNDER_ARMOR
@ SPELL_BRUTAL_STRIKE
@ SPELL_IMPALE
Position const GuardsMovePosition
AzureCaptainSpells
@ SPELL_MORTAL_STRIKE
@ SPELL_WHIRLWIND_OF_STEEL
Position const SaboteurXevozzPath[]
uint8 const PortalIntroCount
Definition violet_hold.h:31
@ DATA_ICHORON
Definition violet_hold.h:55
@ DATA_MAIN_EVENT_STATE
Definition violet_hold.h:61
@ DATA_ZURAMAT
Definition violet_hold.h:58
@ DATA_XEVOZZ
Definition violet_hold.h:57
@ DATA_2ND_BOSS
Definition violet_hold.h:50
@ DATA_1ST_BOSS
Definition violet_hold.h:49
@ DATA_SINCLARI_TRIGGER
Definition violet_hold.h:85
@ DATA_MAIN_DOOR
Definition violet_hold.h:83
@ DATA_EREKEM
Definition violet_hold.h:54
@ DATA_LAVANTHOR
Definition violet_hold.h:56
@ DATA_PORTAL_LOCATION
Definition violet_hold.h:64
@ DATA_DOOR_INTEGRITY
Definition violet_hold.h:63
@ DATA_START_BOSS_ENCOUNTER
Definition violet_hold.h:65
@ DATA_MORAGG
Definition violet_hold.h:53
#define RegisterVioletHoldCreatureAI(ai_name)
@ ACTION_SINCLARI_OUTRO
@ POINT_INTRO
#define RegisterVioletHoldGameObjectAI(ai_name)
@ NPC_TELEPORTATION_PORTAL_INTRO
Definition violet_hold.h:93
@ NPC_VIOLET_HOLD_GUARD
@ NPC_PORTAL_KEEPER
Definition violet_hold.h:95
@ NPC_PORTAL_GUARDIAN
Definition violet_hold.h:94