TrinityCore
Loading...
Searching...
No Matches
the_black_morass.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/*
19 * Movement for Shadow Council Enforcer is NYI
20 * All visuals around Medivh are NYI (see creatures spawned around Medivh)
21 * Timers at which we summon portals requires to be revisited
22 * The way we summon portals may be not entirely correct and requires additional research
23 Current handling is:
24 1. First portal is opened when event starts (correct)
25 2. When Rift Lord or Rift Keeper is defeated, next portal is spawned after 0-5s (timer seems correct)
26 3. When we summon boss, we summon no more portals until boss is defeated (seems to be correct)
27 4. We summon next portal even if previous was not closed. We can have maximum 5 normal portals + 1 boss portal active at once (to be verified)
28 5. We summon no new portal imediately after closing any portal if we already have more than one portal active(to be verified)
29 */
30
31#include "ScriptMgr.h"
32#include "GameObject.h"
33#include "InstanceScript.h"
34#include "Map.h"
35#include "Player.h"
36#include "ScriptedCreature.h"
37#include "SpellAuraEffects.h"
38#include "SpellInfo.h"
39#include "SpellScript.h"
40#include "TemporarySummon.h"
41#include "the_black_morass.h"
42
44{
45 // Medivh
53
54 // Shadow Council Enforcer
55 SAY_RETREAT = 0
56};
57
59{
60 // Medivh
64
65 // Dark Portal Dummy 1.30
66 SPELL_PORTAL_RUNE = 32570, // NYI
67
68 // Dark Portal Black Crystal Invisible Stalker
69 SPELL_BLACK_CRYSTAL = 32563, // NYI
70
71 // Dark Portal Dummy
72 SPELL_PORTAL_CRYSTAL = 32564, // NYI
73
74 // Dark Portal Beam Invisible Stalker
75 SPELL_BANISH_PURPLE = 32566, // NYI
76
77 // Time Rift
79
80 // NYI
96
97 // Scripts
101
106
116
123
135
145
146// 15608 - Medivh
148{
150
157
158 void DoAction(int32 action) override
159 {
160 switch (action)
161 {
165 break;
166 case ACTION_SHIELD_75:
168 break;
169 case ACTION_SHIELD_50:
171 break;
172 case ACTION_SHIELD_25:
174 break;
175 case ACTION_SHIELD_0:
178 break;
179 case ACTION_EPILOGUE:
181 break;
182 default:
183 break;
184 }
185 }
186
188 {
189 std::vector<Creature*> spawns;
190
210
211 for (Creature* spawn : spawns)
212 if (spawn->IsAlive())
213 spawn->DespawnOrUnsummon();
214 }
215
216 void JustDied(Unit* /*killer*/) override
217 {
219 }
220
221 void UpdateAI(uint32 diff) override
222 {
223 _events.Update(diff);
224
225 while (uint32 eventId = _events.ExecuteEvent())
226 {
227 switch (eventId)
228 {
229 case EVENT_EPILOGUE_1:
230 // Guessed. What should happen if portals weren't closed but Aeonus was defeated and epilogue was triggered?
234 break;
235 case EVENT_EPILOGUE_2:
236 me->SetFacingTo(6.2657318115234375f);
237 Talk(SAY_WIN);
238 me->SetImmuneToPC(false);
240 me->SummonGameObject(GO_DARK_PORTAL, -2087.3372f, 7125.657f, 29.942312f, 6.143561f, QuaternionData(0.f, 0.f, -0.069755554f, 0.99756414f), 0s);
242 break;
243 case EVENT_EPILOGUE_3:
244 me->SetFacingTo(3.001966238021850585f);
248 break;
249 case EVENT_EPILOGUE_4:
252 break;
253 case EVENT_EPILOGUE_5:
256 break;
257 case EVENT_EPILOGUE_6:
260 break;
261 case EVENT_EPILOGUE_7:
264 break;
265 case EVENT_EPILOGUE_8:
266 Talk(SAY_ORCS);
267 break;
268 default:
269 break;
270 }
271 }
272 }
273
274private:
276};
277
278// 17838 - Time Rift
280{
282
283 void JustAppeared() override
284 {
286 }
287};
288
289// 31326 - Corrupt Medivh
291{
293
294 void OnPeriodic(AuraEffect const* aurEff)
295 {
296 if (aurEff->GetTickNumber() % 3)
297 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
298 instance->SetData(DATA_SHIELD_PCT, SPECIAL);
299 }
300
305};
306
307// 37853 - Corrupt Medivh
323
324// 31388 - Time Rift Channel Trigger
326{
328
329 bool Validate(SpellInfo const* /*spellInfo*/) override
330 {
332 }
333
334 void HandleScript(SpellEffIndex /*effIndex*/)
335 {
336 if (TempSummon* summon = GetCaster()->ToTempSummon())
337 if (Unit* summoner = summon->GetSummonerUnit())
338 summoner->CastSpell(summon, SPELL_TIME_RIFT_CHANNEL);
339 }
340
345};
346
347// 31550 - Banish Dragon Helper
367
368// 31322 - Close Time Rift Trigger
370{
372
373 bool Validate(SpellInfo const* /*spellInfo*/) override
374 {
376 }
377
378 void HandleScript(SpellEffIndex /*effIndex*/)
379 {
380 if (TempSummon* summon = GetCaster()->ToTempSummon())
381 if (Unit* summoner = summon->GetSummonerUnit())
382 summon->CastSpell(summoner, SPELL_CLOSE_TIME_RIFT_EFFECT);
383 }
384
389};
390
391// 31323 - Close Time Rift Effect
407
408// 31320 - Time Rift Periodic
410{
412
437
438 bool Load() override
439 {
440 if (InstanceScript* instance = GetOwner()->GetInstanceScript())
441 {
442 _instance = instance;
443
445
446 if (_riftCount < 7)
447 _riftWaveId = 0;
448 else if (_riftCount > 6 && _riftCount < 13)
449 _riftWaveId = 1;
450 else if (_riftCount > 12)
451 _riftWaveId = 2;
452
453 return true;
454 }
455
456 return false;
457 }
458
459 void OnPeriodic(AuraEffect const* aurEff)
460 {
461 if (_isLastRift)
462 return;
463
464 Unit* target = GetTarget();
465
466 if (_isFirstSummon)
467 {
468 switch (_riftCount)
469 {
470 case 6:
471 target->CastSpell(nullptr, (_instance->GetBossState(DATA_DEJA) == DONE && target->GetMap()->IsHeroic()) ?
473 break;
474 case 12:
475 target->CastSpell(nullptr, (_instance->GetBossState(DATA_TEMPORUS) == DONE && target->GetMap()->IsHeroic()) ?
477 break;
478 case 18:
479 target->CastSpell(nullptr, SPELL_SUMMON_AEONUS, true);
480 _isLastRift = true;
481 break;
482 default:
484 break;
485 }
486
487 _isFirstSummon = false;
488 const_cast<AuraEffect*>(aurEff)->ResetTicks();
489 }
490 else
491 {
492 switch (_riftWaveId)
493 {
494 case 0:
495 {
496 switch (aurEff->GetTickNumber())
497 {
498 case 1:
500 break;
501 case 2:
502 for (uint8 i = 0; i < 3; ++i)
503 target->CastSpell(nullptr, SPELL_SUMMON_INFINITE_WHELP, true);
504 break;
505 case 3:
507 const_cast<AuraEffect*>(aurEff)->ResetTicks();
508 break;
509 default:
510 break;
511 }
512 break;
513 }
514 case 1:
515 {
516 switch (aurEff->GetTickNumber())
517 {
518 case 1:
520 break;
521 case 2:
523 break;
524 case 3:
525 for (uint8 i = 0; i < 3; ++i)
526 target->CastSpell(nullptr, SPELL_SUMMON_INFINITE_WHELP, true);
527 break;
528 case 4:
530 const_cast<AuraEffect*>(aurEff)->ResetTicks();
531 break;
532 default:
533 break;
534 }
535 break;
536 }
537 case 2:
538 {
539 switch (aurEff->GetTickNumber())
540 {
541 case 1:
543 break;
544 case 2:
546 break;
547 case 3:
549 break;
550 case 4:
552 const_cast<AuraEffect*>(aurEff)->ResetTicks();
553 break;
554 default:
555 break;
556 }
557 break;
558 }
559 default:
560 break;
561 }
562 }
563 }
564
569
570private:
573 bool _isLastRift = false;
574 bool _isFirstSummon = true;
576};
577
578// 4288
580{
581 public:
582 at_black_morass_medivh() : AreaTriggerScript("at_black_morass_medivh") { }
583
584 bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
585 {
586 if (InstanceScript* instance = player->GetInstanceScript())
587 {
588 if (instance->GetBossState(DATA_AEONUS) == DONE || instance->GetData(DATA_EVENT) == IN_PROGRESS || instance->GetData(DATA_EVENT) == DONE)
589 return false;
590
591 if (Creature* medivh = instance->GetCreature(DATA_MEDIVH))
592 {
593 if (medivh->IsAlive())
594 {
595 medivh->AI()->DoAction(ACTION_START_EVENT);
596 instance->SetData(DATA_EVENT, IN_PROGRESS);
597 }
598 }
599
600 return false;
601 }
602 return false;
603 }
604};
605
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
@ IN_PROGRESS
@ DONE
@ SPECIAL
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_SCRIPT_EFFECT
@ EMOTE_STATE_TALK
@ EMOTE_ONESHOT_NONE
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
#define SpellEffectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
@ UNIT_NPC_FLAG_QUESTGIVER
@ UNIT_NPC_FLAGS
@ DATA_EVENT
uint32 GetTickNumber() const
HookList< EffectPeriodicHandler > OnEffectPeriodic
WorldObject * GetOwner() const
Unit * GetTarget() const
Creature *const me
Definition CreatureAI.h:82
void SetImmuneToPC(bool apply) override
Definition Creature.h:138
void Update(uint32 time)
Definition EventMap.h:67
EventId ExecuteEvent()
Definition EventMap.cpp:73
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
EncounterState GetBossState(uint32 id) const
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn=false, bool force=false, std::vector< WorldObject * > *spawnedObjects=nullptr)
Definition Map.cpp:3382
bool IsHeroic() const
Definition Map.cpp:4251
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:761
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
Definition Unit.h:783
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1112
void SetEmoteState(Emote emote)
Definition Unit.h:981
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3807
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13226
Map * GetMap() const
Definition Object.h:451
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1088
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2833
GameObject * SummonGameObject(uint32 entry, Position const &pos, QuaternionData const &rot, Seconds respawnTime, GOSummonType summonType=GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)
Definition Object.cpp:2016
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:55
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnTrigger(Player *player, AreaTriggerEntry const *) override
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_black_morass_banish_dragon_helper)
PrepareSpellScript(spell_black_morass_close_time_rift_effect)
PrepareSpellScript(spell_black_morass_close_time_rift_trigger)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_black_morass_corrupt_medivh_aeonus)
void OnPeriodic(AuraEffect const *aurEff)
PrepareAuraScript(spell_black_morass_corrupt_medivh)
bool Validate(SpellInfo const *) override
PrepareSpellScript(spell_black_morass_time_rift_channel_trigger)
PrepareAuraScript(spell_black_morass_time_rift_periodic)
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *aurEff)
ScriptedAI(Creature *creature)
void JustAppeared() override
void JustDied(Unit *) override
void DoAction(int32 action) override
void UpdateAI(uint32 diff) override
void JustAppeared() override
MedivhBlackMorassMisc
@ SPAWN_GROUP_ENFORCERS_4
@ SPAWN_GROUP_ENFORCERS_1
@ GO_DARK_PORTAL
@ ACTION_START_EVENT
@ SPAWN_GROUP_ENFORCERS_3
@ SPAWN_GROUP_ENFORCERS_2
void AddSC_the_black_morass()
MedivhBlackMorassTexts
@ SAY_DEATH
@ SAY_WIN
@ SAY_SHIELD_75
@ SAY_SHIELD_50
@ SAY_ORCS
@ SAY_RETREAT
@ SAY_ENTER
@ SAY_SHIELD_25
MedivhBlackMorassEvents
@ EVENT_EPILOGUE_5
@ EVENT_EPILOGUE_8
@ EVENT_EPILOGUE_1
@ EVENT_EPILOGUE_4
@ EVENT_EPILOGUE_6
@ EVENT_EPILOGUE_7
@ EVENT_EPILOGUE_2
@ EVENT_EPILOGUE_3
MedivhBlackMorassSpells
@ SPELL_SUMMON_INFINITE_CHRONO_LORD
@ SPELL_BLACK_CRYSTAL
@ SPELL_TIME_RIFT_3_READY
@ SPELL_TIME_RIFT_1_READY
@ SPELL_SUMMON_RIFT_KEEPER
@ SPELL_SUMMON_INFINITE_CHRONOMANCER
@ SPELL_TIME_RIFT_4_READY
@ SPELL_SUMMON_RIFT_LORD_2
@ SPELL_TIME_RIFT_CHANNEL
@ SPELL_MEDIVH_SHIELD
@ SPELL_MANA_SHIELD
@ SPELL_SUMMON_TIME_RIFT
@ SPELL_SUMMON_TIME_RIFT_PERIODIC_5
@ SPELL_SUMMON_TEMPORUS
@ SPELL_SUMMON_INFINITE_EXECUTIONER
@ SPELL_TIME_RIFT_PERIODIC
@ SPELL_DRAGON_HELPER_EFFECT
@ SPELL_SUMMON_RIFT_KEEPER_2
@ SPELL_SUMMON_INFINITE_ASSASSIN
@ SPELL_SUMMON_TIME_RIFT_PERIODIC_75
@ SPELL_SUMMON_TIME_RIFT_PERIODIC_90
@ SPELL_SUMMON_INFINITE_VANQUISHER
@ SPELL_SUMMON_INFINITE_TIMEREAVER
@ SPELL_PORTAL_CRYSTAL
@ SPELL_PORTAL_RUNE
@ SPELL_SUMMON_INFINITE_ASSASSIN_2
@ SPELL_TIME_RIFT_2_READY
@ SPELL_SUMMON_INFINITE_EXECUTIONER_2
@ SPELL_CLOSE_TIME_RIFT_EFFECT
@ SPELL_MEDIVH_DIES
@ SPELL_MEDIVH_CHANNEL
@ SPELL_SUMMON_INFINITE_WHELP
@ SPELL_SUMMON_TIME_RIFT_PERIODIC_30
@ SPELL_SUMMON_AEONUS
@ SPELL_SUMMON_RIFT_LORD
@ SPELL_BANISH_PURPLE
@ SPELL_QUIET_SUICIDE
@ SPELL_SUMMON_INFINITE_CHRONOMANCER_2
@ SPELL_SUMMON_INFINITE_VANQUISHER_2
@ SPELL_SUMMON_TIME_RIFT_PERIODIC_120
@ SPELL_TIME_RIFT_READY_PRIMER
@ SPELL_SUMMON_TIME_RIFT_PERIODIC_45
@ SPELL_SUMMON_CHRONO_LORD_DEJA
@ SPELL_MEDIVH_LIVES
@ ACTION_SHIELD_25
@ ACTION_EPILOGUE
@ ACTION_SHIELD_0
@ ACTION_SHIELD_75
@ ACTION_SHIELD_50
@ NPC_AEONUS
@ NPC_INFINITE_EXECUTIONER
@ NPC_INFINITE_VANQUISHER_ALT
@ NPC_INFINITE_WHELP
@ NPC_INFINITE_VANQUISHER
@ NPC_INFINITE_TIMEREAVER
@ NPC_INFINITE_CRONOMANCER
@ NPC_RIFT_LORD_ALT
@ NPC_INFINITE_CHRONO_LORD
@ NPC_RIFT_KEEPER
@ NPC_INFINITE_ASSASIN_ALT
@ NPC_INFINITE_ASSASIN
@ NPC_RIFT_LORD
@ NPC_INFINITE_CRONOMANCER_ALT
@ NPC_TEMPORUS
@ NPC_RIFT_KEEPER_ALT
@ NPC_CRONO_LORD_DEJA
@ NPC_INFINITE_EXECUTIONER_ALT
@ DATA_MEDIVH
@ DATA_TEMPORUS
@ DATA_RIFT_COUNT
@ DATA_SHIELD_PCT
@ DATA_DEJA
@ DATA_AEONUS
#define RegisterBlackMorassCreatureAI(ai_name)