TrinityCore
Loading...
Searching...
No Matches
instance_stratholme.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/* ScriptData
19SDName: instance_stratholme
20SD%Complete: 50
21SDComment: In progress. Undead side 75% implemented. Save/load not implemented.
22SDCategory: Stratholme
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "Creature.h"
27#include "CreatureAI.h"
28#include "EventMap.h"
29#include "GameObject.h"
30#include "InstanceScript.h"
31#include "Log.h"
32#include "Map.h"
33#include "MotionMaster.h"
34#include "Pet.h"
35#include "Player.h"
36#include "stratholme.h"
37
44
49
50static constexpr DungeonEncounterData Encounters[] =
51{
52 { BOSS_HEARTHSINGER_FORRESTEN, {{ 473 }} }, // Hearthsinger Forresten
53 { BOSS_TIMMY_THE_CRUEL, {{ 474 }} }, // Timmy the Cruel
54 { BOSS_COMMANDER_MALOR, {{ 476 }} }, // Commander Malor
55 { BOSS_WILLEY_HOPEBREAKER, {{ 475 }} }, // Willey Hopebreaker
56 { BOSS_INSTRUCTOR_GALFORD, {{ 477 }} }, // Instructor Galford
57 { BOSS_BALNAZZAR, {{ 478 }} }, // Balnazzar
58 { BOSS_THE_UNFORGIVEN, {{ 472 }} }, // The Unforgiven
59 { BOSS_BARONESS_ANASTARI, {{ 479 }} }, // Baroness Anastari
60 { BOSS_NERUB_ENKAN, {{ 480 }} }, // Nerub'enkan
61 { BOSS_MALEKI_THE_PALLID, {{ 481 }} }, // Maleki the Pallid
62 { BOSS_MAGISTRATE_BARTHILAS, {{ 482 }} }, // Magistrate Barthilas
63 { BOSS_RAMSTEIN_THE_GORGER, {{ 483 }} }, // Ramstein the Gorger
64 { BOSS_RIVENDARE, {{ 484 }} }, // Lord Aurius Rivendare
65 { BOSS_POSTMASTER_MALOWN, {{ 1885 }} } // Postmaster Malown
66};
67
69{
70 ScaletSide = 0,
71 UndeadSide = 1
72};
73
74Position const GateTrapPos[] = // Positions of the two Gate Traps 3919.88 -3547.34 134.269
75{
76 { 3612.29f, -3335.39f, 124.077f }, // Scarlet side
77 { 3919.88f, -3545.34f, 134.269f } // Undead side
78};
79
81{
82 std::array<ObjectGuid, 2> Gates;
84 bool Triggered = false;
85};
86
88{
89 public:
91
93 {
108
111
113
125
132
133 std::array<GateTrapData, 2> TrapGates;
134
135 void OnUnitDeath(Unit* who) override
136 {
137 switch (who->GetEntry())
138 {
141 break;
144 break;
147 break;
150 break;
151 default:
152 break;
153 case NPC_PLAGUED_RAT:
154 {
155 for (GateTrapData& trapGate : TrapGates)
156 {
157 auto el = trapGate.Rats.find(who->GetGUID());
158 if (el != trapGate.Rats.end())
159 {
160 trapGate.Rats.erase(el);
161 for (ObjectGuid gate : trapGate.Gates)
163 }
164 }
165 break;
166 }
167 }
168 }
169
171 {
172 if (brokenCrystals >= 3)
173 {
176 return true;
177 }
178
179 TC_LOG_DEBUG("scripts", "Instance Stratholme: Cannot open slaugther square yet.");
180 return false;
181 }
182
183 //if restoreTime is not 0, then newState will be ignored and GO should be restored to original state after "restoreTime" millisecond
184 void UpdateGoState(ObjectGuid goGuid, uint32 newState, uint32 restoreTime = 0u)
185 {
186 if (!goGuid)
187 return;
188 if (GameObject* go = instance->GetGameObject(goGuid))
189 {
190 if (restoreTime)
191 go->UseDoorOrButton(restoreTime);
192 else
193 go->SetGoState((GOState)newState);
194 }
195 }
196
198 {
199 // close the gate, but in two minutes it will open on its own
200 for (ObjectGuid trapGateGuid : TrapGates[AsUnderlyingType(type)].Gates)
201 UpdateGoState(trapGateGuid, GO_STATE_READY, 20 * IN_MILLISECONDS);
202
203 for (uint8 i = 0; i < 30; ++i)
204 {
205 Position summonPos = where->GetRandomPoint(GateTrapPos[AsUnderlyingType(type)], 5.0f);
206 if (Creature* creature = where->SummonCreature(NPC_PLAGUED_RAT, summonPos, TEMPSUMMON_DEAD_DESPAWN, 0s))
207 {
208 TrapGates[AsUnderlyingType(type)].Rats.insert(creature->GetGUID());
209 creature->EngageWithTarget(where);
210 }
211 }
212
213 TrapGates[AsUnderlyingType(type)].Triggered = true;
214 }
215
216 void OnCreatureCreate(Creature* creature) override
217 {
218 switch (creature->GetEntry())
219 {
220 case NPC_BARON:
221 baronGUID = creature->GetGUID();
222 break;
224 ysidaTriggerGUID = creature->GetGUID();
225 break;
226 case NPC_CRYSTAL:
227 crystalsGUID.insert(creature->GetGUID());
228 break;
229 case NPC_ABOM_BILE:
230 case NPC_ABOM_VENOM:
231 abomnationGUID.insert(creature->GetGUID());
232 break;
233 case NPC_YSIDA:
234 ysidaGUID = creature->GetGUID();
236 break;
237 }
238 }
239
240 void OnCreatureRemove(Creature* creature) override
241 {
242 switch (creature->GetEntry())
243 {
244 case NPC_CRYSTAL:
245 crystalsGUID.erase(creature->GetGUID());
246 break;
247 case NPC_ABOM_BILE:
248 case NPC_ABOM_VENOM:
249 abomnationGUID.erase(creature->GetGUID());
250 break;
251 }
252 }
253
255 {
256 switch (go->GetEntry())
257 {
260 break;
262 //weird, but unless flag is set, client will not respond as expected. DB bug?
265 break;
266 case GO_ZIGGURAT1:
267 ziggurat1GUID = go->GetGUID();
270 break;
271 case GO_ZIGGURAT2:
272 ziggurat2GUID = go->GetGUID();
275 break;
276 case GO_ZIGGURAT3:
277 ziggurat3GUID = go->GetGUID();
280 break;
281 case GO_ZIGGURAT4:
282 ziggurat4GUID = go->GetGUID();
285 break;
286 case GO_ZIGGURAT5:
287 ziggurat5GUID = go->GetGUID();
290 break;
291 case GO_PORT_GAUNTLET:
293 if (brokenCrystals >= 3)
295 break;
298 if (brokenCrystals >= 3)
300 break;
301 case GO_PORT_ELDERS:
302 portElderGUID = go->GetGUID();
303 break;
304 case GO_YSIDA_CAGE:
305 ysidaCageGUID = go->GetGUID();
306 break;
309 break;
312 break;
315 break;
318 break;
319 }
320 }
321
322 bool SetBossState(uint32 id, EncounterState state) override
323 {
324 if (!InstanceScript::SetBossState(id, state))
325 return false;
326
327 switch (id)
328 {
330 if (state == DONE)
331 {
333
334 //remove when crystals implemented
337 }
338 break;
339 case BOSS_NERUB_ENKAN:
340 if (state == DONE)
341 {
343
344 //remove when crystals implemented
347 }
348 break;
350 if (state == DONE)
351 {
353
354 //remove when crystals implemented
357 }
358 break;
360 if (state == NOT_STARTED)
362
363 if (state == DONE)
364 {
366 TC_LOG_DEBUG("scripts", "Instance Stratholme: Slaugther event will continue in 1 minute.");
367 }
368 break;
369 case BOSS_RIVENDARE:
372 if (state == DONE)
373 {
377
379 }
380 break;
381 default:
382 break;
383 }
384
385 return true;
386 }
387
388 void SetData(uint32 type, uint32 data) override
389 {
390 switch (type)
391 {
392 case TYPE_BARON_RUN:
393 switch (data)
394 {
395 case IN_PROGRESS:
397 break;
400 TC_LOG_DEBUG("scripts", "Instance Stratholme: Baron run in progress.");
401 break;
402 case FAIL:
404 if (Creature* ysida = instance->GetCreature(ysidaGUID))
405 ysida->CastSpell(ysida, SPELL_PERM_FEIGN_DEATH, true);
407 break;
408 case DONE:
410
411 if (Creature* ysida = instance->GetCreature(ysidaGUID))
412 {
414 cage->UseDoorOrButton();
415
416 float x, y, z;
418 ysida->CastSpell(nullptr, SPELL_YSIDA_SAVED, true);
419 ysida->SetWalk(true);
420 ysida->AI()->Talk(SAY_YSIDA_SAVED);
421 ysida->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
422 ysida->GetClosePoint(x, y, z, ysida->GetObjectScale() / 3, 4.0f);
423 ysida->GetMotionMaster()->MovePoint(1, x, y, z);
424
425 Map::PlayerList const& players = instance->GetPlayers();
426
427 for (auto const& i : players)
428 {
429 if (Player* player = i.GetSource())
430 {
431 if (player->IsGameMaster())
432 continue;
433
436 player->CastSpell(ysida, SPELL_YSIDA_CREDIT_EFFECT, true);
437 }
438 }
439 }
441 break;
442 }
443 break;
444 case TYPE_RAMSTEIN:
445 if (data == IN_PROGRESS)
446 {
448
449 uint32 count = abomnationGUID.size();
450 for (GuidSet::const_iterator i = abomnationGUID.begin(); i != abomnationGUID.end(); ++i)
451 {
452 if (Creature* pAbom = instance->GetCreature(*i))
453 if (!pAbom->IsAlive())
454 --count;
455 }
456
457 if (!count)
458 {
459 //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now.
460 //UpdateGoState(ziggurat4GUID, 0, true);
461 if (Creature* pBaron = instance->GetCreature(baronGUID))
462 pBaron->SummonCreature(NPC_RAMSTEIN, 4032.84f, -3390.24f, 119.73f, 4.71f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30min);
463 TC_LOG_DEBUG("scripts", "Instance Stratholme: Ramstein spawned.");
464 }
465 else
466 TC_LOG_DEBUG("scripts", "Instance Stratholme: {} Abomnation left to kill.", count);
467 }
468 break;
469 case TYPE_SH_AELMAR:
470 IsSilverHandDead[0] = (data) ? true : false;
471 break;
472 case TYPE_SH_CATHELA:
473 IsSilverHandDead[1] = (data) ? true : false;
474 break;
475 case TYPE_SH_GREGOR:
476 IsSilverHandDead[2] = (data) ? true : false;
477 break;
478 case TYPE_SH_NEMAS:
479 IsSilverHandDead[3] = (data) ? true : false;
480 break;
481 case TYPE_SH_VICAR:
482 IsSilverHandDead[4] = (data) ? true : false;
483 break;
484 default:
485 break;
486 }
487 }
488
489 uint32 GetData(uint32 type) const override
490 {
491 switch (type)
492 {
493 case TYPE_SH_QUEST:
495 return 1;
496 return 0;
497 case TYPE_BARON_RUN:
498 return baronRunState;
499 case TYPE_BARONESS:
501 case TYPE_NERUB:
503 case TYPE_PALLID:
505 case TYPE_RAMSTEIN:
507 case TYPE_BARON:
509 default:
510 break;
511 }
512 return 0;
513 }
514
515 ObjectGuid GetGuidData(uint32 data) const override
516 {
517 switch (data)
518 {
519 case DATA_BARON:
520 return baronGUID;
522 return ysidaTriggerGUID;
523 case NPC_YSIDA:
524 return ysidaGUID;
525 default:
526 break;
527 }
528 return ObjectGuid::Empty;
529 }
530
531 void Update(uint32 diff) override
532 {
533 events.Update(diff);
534
535 while (uint32 eventId = events.ExecuteEvent())
536 {
537 switch (eventId)
538 {
539 case EVENT_BARON_RUN:
542 TC_LOG_DEBUG("scripts", "Instance Stratholme: Baron run event reached end. Event has state {}.", GetData(TYPE_BARON_RUN));
543 break;
547 TC_LOG_DEBUG("scripts", "Instance Stratholme: Opening gates to baron.");
548 break;
550 {
551 for (uint8 i = 0; i < std::size(GateTrapPos); ++i)
552 {
553 if (TrapGates[i].Triggered)
554 continue;
555
556 Position const* gateTrapPos = &GateTrapPos[i];
557 // Check that the trap is not on cooldown, if so check if player/pet is in range
558 for (MapReference const& itr : instance->GetPlayers())
559 {
560 Player* player = itr.GetSource();
561 if (player->IsGameMaster())
562 continue;
563
564 if (player->IsWithinDist2d(gateTrapPos, 5.5f))
565 {
567 break;
568 }
569
570 Pet* pet = player->GetPet();
571 if (pet && pet->IsWithinDist2d(gateTrapPos, 5.5f))
572 {
574 break;
575 }
576 }
577
578 }
579 //if you haven't already fallen into the trap, update it
580 if (std::any_of(TrapGates.begin(), TrapGates.end(), [](GateTrapData const& trap) { return !trap.Triggered; }))
582 break;
583 }
584 default:
585 break;
586 }
587 }
588 }
589
601 };
602
604 {
606 }
607};
608
@ IN_MILLISECONDS
Definition Common.h:38
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
EncounterState
@ IN_PROGRESS
@ FAIL
@ DONE
@ NOT_STARTED
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
@ TEMPSUMMON_DEAD_DESPAWN
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
std::unordered_set< ObjectGuid > GuidUnorderedSet
Definition ObjectGuid.h:435
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:432
@ GO_FLAG_LOCKED
GOState
@ GO_STATE_READY
@ GO_STATE_ACTIVE
@ UNIT_NPC_FLAG_QUESTGIVER
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
#define DataHeader
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void SetFlag(GameObjectFlags flags)
Definition GameObject.h:283
void SetBossNumber(uint32 number)
virtual bool SetBossState(uint32 id, EncounterState state)
void DoRemoveAurasDueToSpellOnPlayers(uint32 spell, bool includePets=false, bool includeControlled=false)
void HandleGameObject(ObjectGuid guid, bool open, GameObject *go=nullptr)
InstanceMap * instance
void SetHeaders(std::string_view dataHeaders)
void LoadDungeonEncounterData(std::span< DungeonEncounterData const > encounters)
EncounterState GetBossState(uint32 id) const
GameObject * GetGameObject(ObjectGuid const &guid)
Definition Map.cpp:3588
PlayerList const & GetPlayers() const
Definition Map.h:408
Creature * GetCreature(ObjectGuid const &guid)
Definition Map.cpp:3578
static ObjectGuid const Empty
Definition ObjectGuid.h:314
uint32 GetEntry() const
Definition Object.h:89
Definition Pet.h:40
Pet * GetPet() const
Definition Player.cpp:22007
bool IsGameMaster() const
Definition Player.h:1293
Definition Unit.h:647
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1013
bool IsWithinDist2d(float x, float y, float dist) const
Definition Object.cpp:484
Position GetRandomPoint(Position const &srcPos, float distance, float minDistance=0.0f) const
Definition Object.cpp:678
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:1403
InstanceScript * GetInstanceScript(InstanceMap *map) const override
#define MAX_ENCOUNTER
static constexpr DungeonEncounterData Encounters[]
@ SAY_YSIDA_SAVED
void AddSC_instance_stratholme()
@ EVENT_SLAUGHTER_SQUARE
@ EVENT_BARON_RUN
@ EVENT_RAT_TRAP_CLOSE
Position const GateTrapPos[]
StratholmeGateTrapType
@ BOSS_MALEKI_THE_PALLID
Definition stratholme.h:37
@ BOSS_TIMMY_THE_CRUEL
Definition stratholme.h:29
@ BOSS_HEARTHSINGER_FORRESTEN
Definition stratholme.h:28
@ BOSS_BALNAZZAR
Definition stratholme.h:33
@ BOSS_NERUB_ENKAN
Definition stratholme.h:36
@ BOSS_RIVENDARE
Definition stratholme.h:40
@ BOSS_INSTRUCTOR_GALFORD
Definition stratholme.h:32
@ BOSS_MAGISTRATE_BARTHILAS
Definition stratholme.h:38
@ BOSS_BARONESS_ANASTARI
Definition stratholme.h:35
@ BOSS_RAMSTEIN_THE_GORGER
Definition stratholme.h:39
@ BOSS_POSTMASTER_MALOWN
Definition stratholme.h:41
@ BOSS_COMMANDER_MALOR
Definition stratholme.h:30
@ BOSS_THE_UNFORGIVEN
Definition stratholme.h:34
@ BOSS_WILLEY_HOPEBREAKER
Definition stratholme.h:31
@ NPC_THE_UNFORGIVEN
Definition stratholme.h:71
@ NPC_HEARTHSINGER_FORRESTEN
Definition stratholme.h:68
@ NPC_YSIDA
Definition stratholme.h:81
@ NPC_RAMSTEIN
Definition stratholme.h:77
@ NPC_BARON
Definition stratholme.h:74
@ NPC_CRYSTAL
Definition stratholme.h:73
@ NPC_ABOM_BILE
Definition stratholme.h:78
@ NPC_ABOM_VENOM
Definition stratholme.h:79
@ NPC_YSIDA_TRIGGER
Definition stratholme.h:75
@ NPC_INSTRUCTOR_GALFORD
Definition stratholme.h:70
@ NPC_COMMANDER_MALOR
Definition stratholme.h:69
@ NPC_PLAGUED_RAT
Definition stratholme.h:92
@ SPELL_PERM_FEIGN_DEATH
Definition stratholme.h:123
@ SPELL_YSIDA_SAVED
Definition stratholme.h:124
@ SPELL_YSIDA_CREDIT_EFFECT
Definition stratholme.h:125
@ SPELL_BARON_ULTIMATUM
Definition stratholme.h:122
@ GO_PORT_TRAP_GATE_4
Definition stratholme.h:112
@ GO_PORT_TRAP_GATE_1
Definition stratholme.h:109
@ GO_GAUNTLET_GATE1
Definition stratholme.h:99
@ GO_ZIGGURAT1
Definition stratholme.h:100
@ GO_ZIGGURAT3
Definition stratholme.h:102
@ GO_PORT_TRAP_GATE_3
Definition stratholme.h:111
@ GO_ZIGGURAT4
Definition stratholme.h:103
@ GO_PORT_TRAP_GATE_2
Definition stratholme.h:110
@ GO_ZIGGURAT2
Definition stratholme.h:101
@ GO_ZIGGURAT5
Definition stratholme.h:104
@ GO_PORT_ELDERS
Definition stratholme.h:107
@ GO_SERVICE_ENTRANCE
Definition stratholme.h:98
@ GO_PORT_GAUNTLET
Definition stratholme.h:105
@ GO_PORT_SLAUGTHER
Definition stratholme.h:106
@ GO_YSIDA_CAGE
Definition stratholme.h:108
#define StratholmeScriptName
Definition stratholme.h:23
@ TYPE_SH_CATHELA
Definition stratholme.h:59
@ DATA_BARON
Definition stratholme.h:55
@ TYPE_PALLID
Definition stratholme.h:51
@ TYPE_SH_AELMAR
Definition stratholme.h:63
@ DATA_YSIDA_TRIGGER
Definition stratholme.h:56
@ TYPE_BARONESS
Definition stratholme.h:49
@ TYPE_SH_GREGOR
Definition stratholme.h:60
@ TYPE_SH_NEMAS
Definition stratholme.h:61
@ TYPE_NERUB
Definition stratholme.h:50
@ TYPE_BARON
Definition stratholme.h:53
@ TYPE_SH_VICAR
Definition stratholme.h:62
@ TYPE_RAMSTEIN
Definition stratholme.h:52
@ TYPE_BARON_RUN
Definition stratholme.h:48
@ TYPE_SH_QUEST
Definition stratholme.h:58
std::array< ObjectGuid, 2 > Gates
GuidUnorderedSet Rats
void UpdateGoState(ObjectGuid goGuid, uint32 newState, uint32 restoreTime=0u)
bool SetBossState(uint32 id, EncounterState state) override
void DoGateTrap(StratholmeGateTrapType type, Unit *where)