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 "AreaBoundary.h"
27#include "Creature.h"
28#include "CreatureAI.h"
29#include "EventMap.h"
30#include "GameObject.h"
31#include "InstanceScript.h"
32#include "Log.h"
33#include "Map.h"
34#include "MotionMaster.h"
35#include "Player.h"
36#include "stratholme.h"
37#include "Pet.h"
38
45
50
55
56EllipseBoundary const beforeScarletGate(Position(3671.158f, -3181.79f), 60.0f, 40.0f);
57
59{
60 ScaletSide = 0,
61 UndeadSide = 1
62};
63
64Position const GateTrapPos[] = // Positions of the two Gate Traps 3919.88 -3547.34 134.269
65{
66 { 3612.29f, -3335.39f, 124.077f }, // Scarlet side
67 { 3919.88f, -3545.34f, 134.269f } // Undead side
68};
69
71{
72 std::array<ObjectGuid, 2> Gates;
74 bool Triggered = false;
75};
76
78{
79 public:
81
83 {
99
103
106
118
125
126 std::array<GateTrapData, 2> TrapGates;
127
128 void OnUnitDeath(Unit* who) override
129 {
130 switch (who->GetEntry())
131 {
136 {
137 if (!timmySpawned)
138 {
139 Position pos = who->ToCreature()->GetHomePosition();
140 // check if they're in front of the entrance
142 {
144 {
146 timmySpawned = true;
147 }
148 }
149 }
150 break;
151 }
154 break;
157 break;
160 break;
163 break;
164 default:
165 break;
166 case NPC_PLAGUED_RAT:
167 {
168 for (GateTrapData& trapGate : TrapGates)
169 {
170 auto el = trapGate.Rats.find(who->GetGUID());
171 if (el != trapGate.Rats.end())
172 {
173 trapGate.Rats.erase(el);
174 for (ObjectGuid gate : trapGate.Gates)
176 }
177 }
178 break;
179 }
180 }
181 }
182
184 {
185 if (brokenCrystals >= 3)
186 {
189 return true;
190 }
191
192 TC_LOG_DEBUG("scripts", "Instance Stratholme: Cannot open slaugther square yet.");
193 return false;
194 }
195
196 //if restoreTime is not 0, then newState will be ignored and GO should be restored to original state after "restoreTime" millisecond
197 void UpdateGoState(ObjectGuid goGuid, uint32 newState, uint32 restoreTime = 0u)
198 {
199 if (!goGuid)
200 return;
201 if (GameObject* go = instance->GetGameObject(goGuid))
202 {
203 if (restoreTime)
204 go->UseDoorOrButton(restoreTime);
205 else
206 go->SetGoState((GOState)newState);
207 }
208 }
209
211 {
212 // close the gate, but in two minutes it will open on its own
213 for (ObjectGuid trapGateGuid : TrapGates[AsUnderlyingType(type)].Gates)
214 UpdateGoState(trapGateGuid, GO_STATE_READY, 20 * IN_MILLISECONDS);
215
216 for (uint8 i = 0; i < 30; ++i)
217 {
218 Position summonPos = where->GetRandomPoint(GateTrapPos[AsUnderlyingType(type)], 5.0f);
219 if (Creature* creature = where->SummonCreature(NPC_PLAGUED_RAT, summonPos, TEMPSUMMON_DEAD_DESPAWN, 0s))
220 {
221 TrapGates[AsUnderlyingType(type)].Rats.insert(creature->GetGUID());
222 creature->EngageWithTarget(where);
223 }
224 }
225
226 TrapGates[AsUnderlyingType(type)].Triggered = true;
227 }
228
229 void OnCreatureCreate(Creature* creature) override
230 {
231 switch (creature->GetEntry())
232 {
233 case NPC_BARON:
234 baronGUID = creature->GetGUID();
235 break;
237 ysidaTriggerGUID = creature->GetGUID();
238 break;
239 case NPC_CRYSTAL:
240 crystalsGUID.insert(creature->GetGUID());
241 break;
242 case NPC_ABOM_BILE:
243 case NPC_ABOM_VENOM:
244 abomnationGUID.insert(creature->GetGUID());
245 break;
246 case NPC_YSIDA:
247 ysidaGUID = creature->GetGUID();
249 break;
250 }
251 }
252
253 void OnCreatureRemove(Creature* creature) override
254 {
255 switch (creature->GetEntry())
256 {
257 case NPC_CRYSTAL:
258 crystalsGUID.erase(creature->GetGUID());
259 break;
260 case NPC_ABOM_BILE:
261 case NPC_ABOM_VENOM:
262 abomnationGUID.erase(creature->GetGUID());
263 break;
264 }
265 }
266
268 {
269 switch (go->GetEntry())
270 {
273 break;
275 //weird, but unless flag is set, client will not respond as expected. DB bug?
278 break;
279 case GO_ZIGGURAT1:
280 ziggurat1GUID = go->GetGUID();
283 break;
284 case GO_ZIGGURAT2:
285 ziggurat2GUID = go->GetGUID();
288 break;
289 case GO_ZIGGURAT3:
290 ziggurat3GUID = go->GetGUID();
293 break;
294 case GO_ZIGGURAT4:
295 ziggurat4GUID = go->GetGUID();
298 break;
299 case GO_ZIGGURAT5:
300 ziggurat5GUID = go->GetGUID();
303 break;
304 case GO_PORT_GAUNTLET:
306 if (brokenCrystals >= 3)
308 break;
311 if (brokenCrystals >= 3)
313 break;
314 case GO_PORT_ELDERS:
315 portElderGUID = go->GetGUID();
316 break;
317 case GO_YSIDA_CAGE:
318 ysidaCageGUID = go->GetGUID();
319 break;
322 break;
325 break;
328 break;
331 break;
332 }
333 }
334
335 bool SetBossState(uint32 id, EncounterState state) override
336 {
337 if (!InstanceScript::SetBossState(id, state))
338 return false;
339
340 switch (id)
341 {
343 if (state == DONE)
344 {
346
347 //remove when crystals implemented
350 }
351 break;
352 case BOSS_NERUB_ENKAN:
353 if (state == DONE)
354 {
356
357 //remove when crystals implemented
360 }
361 break;
363 if (state == DONE)
364 {
366
367 //remove when crystals implemented
370 }
371 break;
373 if (state == NOT_STARTED)
375
376 if (state == DONE)
377 {
379 TC_LOG_DEBUG("scripts", "Instance Stratholme: Slaugther event will continue in 1 minute.");
380 }
381 break;
382 case BOSS_RIVENDARE:
385 if (state == DONE)
386 {
390
392 }
393 break;
394 default:
395 break;
396 }
397
398 return true;
399 }
400
401 void SetData(uint32 type, uint32 data) override
402 {
403 switch (type)
404 {
405 case TYPE_BARON_RUN:
406 switch (data)
407 {
408 case IN_PROGRESS:
410 break;
413 TC_LOG_DEBUG("scripts", "Instance Stratholme: Baron run in progress.");
414 break;
415 case FAIL:
417 if (Creature* ysida = instance->GetCreature(ysidaGUID))
418 ysida->CastSpell(ysida, SPELL_PERM_FEIGN_DEATH, true);
420 break;
421 case DONE:
423
424 if (Creature* ysida = instance->GetCreature(ysidaGUID))
425 {
427 cage->UseDoorOrButton();
428
429 float x, y, z;
431 ysida->CastSpell(nullptr, SPELL_YSIDA_SAVED, true);
432 ysida->SetWalk(true);
433 ysida->AI()->Talk(SAY_YSIDA_SAVED);
434 ysida->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
435 ysida->GetClosePoint(x, y, z, ysida->GetObjectScale() / 3, 4.0f);
436 ysida->GetMotionMaster()->MovePoint(1, x, y, z);
437
438 Map::PlayerList const& players = instance->GetPlayers();
439
440 for (auto const& i : players)
441 {
442 if (Player* player = i.GetSource())
443 {
444 if (player->IsGameMaster())
445 continue;
446
449 player->CastSpell(ysida, SPELL_YSIDA_CREDIT_EFFECT, true);
450 }
451 }
452 }
454 break;
455 }
456 break;
457 case TYPE_RAMSTEIN:
458 if (data == IN_PROGRESS)
459 {
461
462 uint32 count = abomnationGUID.size();
463 for (GuidSet::const_iterator i = abomnationGUID.begin(); i != abomnationGUID.end(); ++i)
464 {
465 if (Creature* pAbom = instance->GetCreature(*i))
466 if (!pAbom->IsAlive())
467 --count;
468 }
469
470 if (!count)
471 {
472 //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now.
473 //UpdateGoState(ziggurat4GUID, 0, true);
474 if (Creature* pBaron = instance->GetCreature(baronGUID))
475 pBaron->SummonCreature(NPC_RAMSTEIN, 4032.84f, -3390.24f, 119.73f, 4.71f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30min);
476 TC_LOG_DEBUG("scripts", "Instance Stratholme: Ramstein spawned.");
477 }
478 else
479 TC_LOG_DEBUG("scripts", "Instance Stratholme: {} Abomnation left to kill.", count);
480 }
481 break;
482 case TYPE_SH_AELMAR:
483 IsSilverHandDead[0] = (data) ? true : false;
484 break;
485 case TYPE_SH_CATHELA:
486 IsSilverHandDead[1] = (data) ? true : false;
487 break;
488 case TYPE_SH_GREGOR:
489 IsSilverHandDead[2] = (data) ? true : false;
490 break;
491 case TYPE_SH_NEMAS:
492 IsSilverHandDead[3] = (data) ? true : false;
493 break;
494 case TYPE_SH_VICAR:
495 IsSilverHandDead[4] = (data) ? true : false;
496 break;
497 default:
498 break;
499 }
500 }
501
502 uint32 GetData(uint32 type) const override
503 {
504 switch (type)
505 {
506 case TYPE_SH_QUEST:
508 return 1;
509 return 0;
510 case TYPE_BARON_RUN:
511 return baronRunState;
512 case TYPE_BARONESS:
514 case TYPE_NERUB:
516 case TYPE_PALLID:
518 case TYPE_RAMSTEIN:
520 case TYPE_BARON:
522 default:
523 break;
524 }
525 return 0;
526 }
527
528 ObjectGuid GetGuidData(uint32 data) const override
529 {
530 switch (data)
531 {
532 case DATA_BARON:
533 return baronGUID;
535 return ysidaTriggerGUID;
536 case NPC_YSIDA:
537 return ysidaGUID;
538 default:
539 break;
540 }
541 return ObjectGuid::Empty;
542 }
543
544 void Update(uint32 diff) override
545 {
546 events.Update(diff);
547
548 while (uint32 eventId = events.ExecuteEvent())
549 {
550 switch (eventId)
551 {
552 case EVENT_BARON_RUN:
555 TC_LOG_DEBUG("scripts", "Instance Stratholme: Baron run event reached end. Event has state {}.", GetData(TYPE_BARON_RUN));
556 break;
560 TC_LOG_DEBUG("scripts", "Instance Stratholme: Opening gates to baron.");
561 break;
563 {
564 for (uint8 i = 0; i < std::size(GateTrapPos); ++i)
565 {
566 if (TrapGates[i].Triggered)
567 continue;
568
569 Position const* gateTrapPos = &GateTrapPos[i];
570 // Check that the trap is not on cooldown, if so check if player/pet is in range
571 for (MapReference const& itr : instance->GetPlayers())
572 {
573 Player* player = itr.GetSource();
574 if (player->IsGameMaster())
575 continue;
576
577 if (player->IsWithinDist2d(gateTrapPos, 5.5f))
578 {
580 break;
581 }
582
583 Pet* pet = player->GetPet();
584 if (pet && pet->IsWithinDist2d(gateTrapPos, 5.5f))
585 {
587 break;
588 }
589 }
590
591 }
592 //if you haven't already fallen into the trap, update it
593 if (std::any_of(TrapGates.begin(), TrapGates.end(), [](GateTrapData const& trap) { return !trap.Triggered; }))
595 break;
596 }
597 default:
598 break;
599 }
600 }
601 }
602
603 void ReadSaveDataMore(std::istringstream& /*data*/) override
604 {
611
613 }
614 };
615
617 {
619 }
620};
621
@ IN_MILLISECONDS
Definition Common.h:35
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
EncounterState
@ IN_PROGRESS
@ FAIL
@ DONE
@ NOT_STARTED
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
@ TEMPSUMMON_DEAD_DESPAWN
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
std::unordered_set< ObjectGuid > GuidUnorderedSet
Definition ObjectGuid.h:263
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:260
@ 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:554
#define DataHeader
bool IsWithinBoundary(Position const *pos) const
void GetHomePosition(float &x, float &y, float &z, float &ori) const
Definition Creature.h:295
void Update(uint32 time)
Definition EventMap.h:67
EventId ExecuteEvent()
Definition EventMap.cpp:73
void CancelEvent(EventId eventId)
Definition EventMap.cpp:151
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void SetFlag(GameObjectFlags flags)
Definition GameObject.h:171
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
EncounterState GetBossState(uint32 id) const
void SetHeaders(std::string const &dataHeaders)
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn=false, bool force=false, std::vector< WorldObject * > *spawnedObjects=nullptr)
Definition Map.cpp:3382
GameObject * GetGameObject(ObjectGuid const &guid)
Definition Map.cpp:4430
PlayerList const & GetPlayers() const
Definition Map.h:448
Creature * GetCreature(ObjectGuid const &guid)
Definition Map.cpp:4397
static ObjectGuid const Empty
Definition ObjectGuid.h:140
static Creature * ToCreature(Object *o)
Definition Object.h:186
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
Definition Pet.h:40
Pet * GetPet() const
Definition Player.cpp:20286
bool IsGameMaster() const
Definition Player.h:998
Definition Unit.h:769
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1098
bool IsWithinDist2d(float x, float y, float dist) const
Definition Object.cpp:1177
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
void GetRandomPoint(Position const &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const
Definition Object.cpp:1376
InstanceScript * GetInstanceScript(InstanceMap *map) const override
#define MAX_ENCOUNTER
EllipseBoundary const beforeScarletGate(Position(3671.158f, -3181.79f), 60.0f, 40.0f)
@ SPAWN_GROUP_STR_TIMMY
@ 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_HEARTHSINGER_FORRESTEN
Definition stratholme.h:28
@ BOSS_NERUB_ENKAN
Definition stratholme.h:36
@ BOSS_RIVENDARE
Definition stratholme.h:40
@ BOSS_INSTRUCTOR_GALFORD
Definition stratholme.h:32
@ BOSS_BARONESS_ANASTARI
Definition stratholme.h:35
@ BOSS_RAMSTEIN_THE_GORGER
Definition stratholme.h:39
@ BOSS_COMMANDER_MALOR
Definition stratholme.h:30
@ BOSS_THE_UNFORGIVEN
Definition stratholme.h:34
@ NPC_THE_UNFORGIVEN
Definition stratholme.h:71
@ NPC_CRIMSON_CONJUROR
Definition stratholme.h:85
@ NPC_CRIMSON_GALLANT
Definition stratholme.h:87
@ 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_CRIMSON_GUARDSMAN
Definition stratholme.h:84
@ 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
@ NPC_CRIMSON_INITATE
Definition stratholme.h:86
@ 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
@ TIMMY_THE_CRUEL_CRUSADERS_REQUIRED
amount of crusade monsters required to be killed in order for timmy the cruel to spawn
Definition stratholme.h:131
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)