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{
292 void OnPeriodic(AuraEffect const* aurEff)
293 {
294 if (aurEff->GetTickNumber() % 3)
295 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
296 instance->SetData(DATA_SHIELD_PCT, SPECIAL);
297 }
298
303};
304
305// 37853 - Corrupt Medivh
307{
308 void OnPeriodic(AuraEffect const* /*aurEff*/)
309 {
310 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
311 instance->SetData(DATA_SHIELD_PCT, SPECIAL);
312 }
313
318};
319
320// 31388 - Time Rift Channel Trigger
322{
323 bool Validate(SpellInfo const* /*spellInfo*/) override
324 {
326 }
327
328 void HandleScript(SpellEffIndex /*effIndex*/)
329 {
330 if (TempSummon* summon = GetCaster()->ToTempSummon())
331 if (Unit* summoner = summon->GetSummonerUnit())
332 summoner->CastSpell(summon, SPELL_TIME_RIFT_CHANNEL);
333 }
334
339};
340
341// 31550 - Banish Dragon Helper
359
360// 31322 - Close Time Rift Trigger
362{
363 bool Validate(SpellInfo const* /*spellInfo*/) override
364 {
366 }
367
368 void HandleScript(SpellEffIndex /*effIndex*/)
369 {
370 if (TempSummon* summon = GetCaster()->ToTempSummon())
371 if (Unit* summoner = summon->GetSummonerUnit())
372 summon->CastSpell(summoner, SPELL_CLOSE_TIME_RIFT_EFFECT);
373 }
374
379};
380
381// 31323 - Close Time Rift Effect
383{
384 void HandleScript(SpellEffIndex /*effIndex*/)
385 {
386 if (Creature* creature = GetHitUnit()->ToCreature())
387 creature->DespawnOrUnsummon();
388 }
389
394};
395
396// 31320 - Time Rift Periodic
398{
423
424 bool Load() override
425 {
426 if (InstanceScript* instance = GetOwner()->GetInstanceScript())
427 {
428 _instance = instance;
429
431
432 if (_riftCount < 7)
433 _riftWaveId = 0;
434 else if (_riftCount > 6 && _riftCount < 13)
435 _riftWaveId = 1;
436 else if (_riftCount > 12)
437 _riftWaveId = 2;
438
439 return true;
440 }
441
442 return false;
443 }
444
445 void OnPeriodic(AuraEffect const* aurEff)
446 {
447 if (_isLastRift)
448 return;
449
450 Unit* target = GetTarget();
451
452 if (_isFirstSummon)
453 {
454 switch (_riftCount)
455 {
456 case 6:
457 target->CastSpell(nullptr, (_instance->GetBossState(DATA_DEJA) == DONE && target->GetMap()->IsHeroic()) ?
459 break;
460 case 12:
461 target->CastSpell(nullptr, (_instance->GetBossState(DATA_TEMPORUS) == DONE && target->GetMap()->IsHeroic()) ?
463 break;
464 case 18:
465 target->CastSpell(nullptr, SPELL_SUMMON_AEONUS, true);
466 _isLastRift = true;
467 break;
468 default:
470 break;
471 }
472
473 _isFirstSummon = false;
474 const_cast<AuraEffect*>(aurEff)->ResetTicks();
475 }
476 else
477 {
478 switch (_riftWaveId)
479 {
480 case 0:
481 {
482 switch (aurEff->GetTickNumber())
483 {
484 case 1:
486 break;
487 case 2:
488 for (uint8 i = 0; i < 3; ++i)
489 target->CastSpell(nullptr, SPELL_SUMMON_INFINITE_WHELP, true);
490 break;
491 case 3:
493 const_cast<AuraEffect*>(aurEff)->ResetTicks();
494 break;
495 default:
496 break;
497 }
498 break;
499 }
500 case 1:
501 {
502 switch (aurEff->GetTickNumber())
503 {
504 case 1:
506 break;
507 case 2:
509 break;
510 case 3:
511 for (uint8 i = 0; i < 3; ++i)
512 target->CastSpell(nullptr, SPELL_SUMMON_INFINITE_WHELP, true);
513 break;
514 case 4:
516 const_cast<AuraEffect*>(aurEff)->ResetTicks();
517 break;
518 default:
519 break;
520 }
521 break;
522 }
523 case 2:
524 {
525 switch (aurEff->GetTickNumber())
526 {
527 case 1:
529 break;
530 case 2:
532 break;
533 case 3:
535 break;
536 case 4:
538 const_cast<AuraEffect*>(aurEff)->ResetTicks();
539 break;
540 default:
541 break;
542 }
543 break;
544 }
545 default:
546 break;
547 }
548 }
549 }
550
555
556private:
559 bool _isLastRift = false;
560 bool _isFirstSummon = true;
562};
563
564// 4288
566{
567 public:
568 at_black_morass_medivh() : AreaTriggerScript("at_black_morass_medivh") { }
569
570 bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
571 {
572 if (InstanceScript* instance = player->GetInstanceScript())
573 {
574 if (instance->GetBossState(DATA_AEONUS) == DONE || instance->GetData(DATA_EVENT) == IN_PROGRESS || instance->GetData(DATA_EVENT) == DONE)
575 return false;
576
577 if (Creature* medivh = instance->GetCreature(DATA_MEDIVH))
578 {
579 if (medivh->IsAlive())
580 {
581 medivh->AI()->DoAction(ACTION_START_EVENT);
582 instance->SetData(DATA_EVENT, IN_PROGRESS);
583 }
584 }
585
586 return false;
587 }
588 return false;
589 }
590};
591
First const & RAND(First const &first, Second const &second, Rest const &... rest)
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ IN_PROGRESS
@ DONE
@ SPECIAL
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
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
@ DATA_EVENT
uint32 GetTickNumber() const
HookList< EffectPeriodicHandler > OnEffectPeriodic
WorldObject * GetOwner() const
Unit * GetTarget() const
Creature *const me
Definition CreatureAI.h:63
void SetImmuneToPC(bool apply) override
Definition Creature.h:190
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
EncounterState GetBossState(uint32 id) const
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn=false, bool force=false, std::vector< WorldObject * > *spawnedObjects=nullptr)
Definition Map.cpp:2360
bool IsHeroic() const
Definition Map.cpp:3347
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
Definition Unit.h:647
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1013
void SetEmoteState(Emote emote)
Definition Unit.h:880
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:1012
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
Map * GetMap() const
Definition Object.h:411
InstanceScript * GetInstanceScript() const
Definition Object.cpp:394
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
GameObject * SummonGameObject(uint32 entry, Position const &pos, QuaternionData const &rot, Seconds respawnTime, GOSummonType summonType=GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)
Definition Object.cpp:1446
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:99
bool OnTrigger(Player *player, AreaTriggerEntry const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *aurEff)
ScriptedAI(Creature *creature, uint32 scriptId=0) noexcept
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)