TrinityCore
blackrock_depths.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 "blackrock_depths.h"
20#include "GameObject.h"
21#include "GameObjectAI.h"
22#include "InstanceScript.h"
23#include "Log.h"
24#include "ObjectAccessor.h"
25#include "Player.h"
26#include "ScriptedEscortAI.h"
27#include "ScriptedGossip.h"
28#include "TemporarySummon.h"
29#include "WorldSession.h"
30
31//go_shadowforge_brazier
33{
34 public:
35 go_shadowforge_brazier() : GameObjectScript("go_shadowforge_brazier") { }
36
38 {
39 go_shadowforge_brazierAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
40
42
43 bool OnGossipHello(Player* /*player*/) override
44 {
47 else
49 // If used brazier open linked doors (North or South)
54
55 return false;
56 }
57 };
58
59 GameObjectAI* GetAI(GameObject* go) const override
60 {
61 return GetBlackrockDepthsAI<go_shadowforge_brazierAI>(go);
62 }
63};
64
65// npc_grimstone
67{
69 NPC_THELDREN = 16059,
70
71 //4 or 6 in total? 1+2+1 / 2+2+2 / 3+3. Depending on this, code should be changed.
73};
74
76{
77 8925, // Dredge Worm
78 8926, // Deep Stinger
79 8927, // Dark Screecher
80 8928, // Burrowing Thundersnout
81 8933, // Cave Creeper
82 8932, // Borer Beetle
83};
84
86{
87 9027, // Gorosh
88 9028, // Grizzle
89 9029, // Eviscerator
90 9030, // Ok'thor
91 9031, // Anub'shiah
92 9032, // Hedrum
93};
94
96{
97public:
98 at_ring_of_law() : AreaTriggerScript("at_ring_of_law") { }
99
100 bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
101 {
102 if (InstanceScript* instance = player->GetInstanceScript())
103 {
104 if (instance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || instance->GetData(TYPE_RING_OF_LAW) == DONE)
105 return false;
106
107 instance->SetData(TYPE_RING_OF_LAW, IN_PROGRESS);
108 player->SummonCreature(NPC_GRIMSTONE, 625.559f, -205.618f, -52.735f, 2.609f, TEMPSUMMON_DEAD_DESPAWN);
109
110 return false;
111 }
112 return false;
113 }
114};
115
116// npc_grimstone
118{
124 SAY_TEXT6 = 5
126
127static constexpr uint32 PATH_ESCORT_GRIMSTONE = 80770;
128
131{
132public:
133 npc_grimstone() : CreatureScript("npc_grimstone") { }
134
135 CreatureAI* GetAI(Creature* creature) const override
136 {
137 return GetBlackrockDepthsAI<npc_grimstoneAI>(creature);
138 }
139
140 struct npc_grimstoneAI : public EscortAI
141 {
142 npc_grimstoneAI(Creature* creature) : EscortAI(creature)
143 {
144 Initialize();
145 instance = creature->GetInstanceScript();
146 MobSpawnId = rand32() % 6;
147 }
148
150 {
151 EventPhase = 0;
152 Event_Timer = 1000;
153
154 MobCount = 0;
155 MobDeath_Timer = 0;
156
157 for (uint8 i = 0; i < MAX_NPC_AMOUNT; ++i)
158 RingMobGUID[i].Clear();
159
161
162 CanWalk = false;
163 }
164
166
169
173
176
178
179 void Reset() override
180 {
181 Initialize();
182 }
183
186 {
187 if (Creature* tmp = me->SummonCreature(RingMob[MobSpawnId], 608.960f, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN))
188 RingMobGUID[MobCount] = tmp->GetGUID();
189
190 ++MobCount;
191
193 MobDeath_Timer = 2500;
194 }
195
198 {
199 if (Creature* tmp = me->SummonCreature(RingBoss[rand32() % 6], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN))
200 RingBossGUID = tmp->GetGUID();
201
202 MobDeath_Timer = 2500;
203 }
204
205 void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
206 {
207 switch (waypointId)
208 {
209 case 0:
211 CanWalk = false;
212 Event_Timer = 5000;
213 break;
214 case 1:
216 CanWalk = false;
217 Event_Timer = 5000;
218 break;
219 case 2:
220 CanWalk = false;
221 break;
222 case 3:
224 break;
225 case 4:
227 CanWalk = false;
228 Event_Timer = 5000;
229 break;
230 case 5:
232 TC_LOG_DEBUG("scripts", "npc_grimstone: event reached end and set complete.");
233 break;
234 }
235 }
236
237 void HandleGameObject(uint32 id, bool open)
238 {
240 }
241
242 void UpdateAI(uint32 diff) override
243 {
244 if (MobDeath_Timer)
245 {
246 if (MobDeath_Timer <= diff)
247 {
248 MobDeath_Timer = 2500;
249
250 if (!RingBossGUID.IsEmpty())
251 {
253 if (boss && !boss->IsAlive() && boss->isDead())
254 {
256 Event_Timer = 5000;
257 MobDeath_Timer = 0;
258 return;
259 }
260 return;
261 }
262
263 for (uint8 i = 0; i < MAX_NPC_AMOUNT; ++i)
264 {
266 if (mob && !mob->IsAlive() && mob->isDead())
267 {
268 RingMobGUID[i].Clear();
269 --MobCount;
270
271 //seems all are gone, so set timer to continue and discontinue this
272 if (!MobCount)
273 {
274 Event_Timer = 5000;
275 MobDeath_Timer = 0;
276 }
277 }
278 }
279 } else MobDeath_Timer -= diff;
280 }
281
282 if (Event_Timer)
283 {
284 if (Event_Timer <= diff)
285 {
286 switch (EventPhase)
287 {
288 case 0:
292 Start(false);
293 CanWalk = true;
294 Event_Timer = 0;
295 break;
296 case 1:
297 CanWalk = true;
298 Event_Timer = 0;
299 break;
300 case 2:
301 Event_Timer = 2000;
302 break;
303 case 3:
305 Event_Timer = 3000;
306 break;
307 case 4:
308 CanWalk = true;
309 me->SetVisible(false);
311 Event_Timer = 8000;
312 break;
313 case 5:
316 Event_Timer = 8000;
317 break;
318 case 6:
320 Event_Timer = 5000;
321 break;
322 case 7:
323 me->SetVisible(true);
326 CanWalk = true;
327 Event_Timer = 5000;
328 break;
329 case 8:
331 Event_Timer = 5000;
332 break;
333 case 9:
334 me->SetVisible(false);
336 Event_Timer = 0;
337 break;
338 case 10:
339 //if quest, complete
343 CanWalk = true;
344 Event_Timer = 0;
345 break;
346 }
347 ++EventPhase;
348 } else Event_Timer -= diff;
349 }
350
351 if (CanWalk)
352 EscortAI::UpdateAI(diff);
353 }
354 };
355};
356
357// npc_phalanx
359{
362 SPELL_MIGHTYBLOW = 14099
364
366{
367public:
368 npc_phalanx() : CreatureScript("npc_phalanx") { }
369
370 CreatureAI* GetAI(Creature* creature) const override
371 {
372 return GetBlackrockDepthsAI<npc_phalanxAI>(creature);
373 }
374
375 struct npc_phalanxAI : public BossAI
376 {
378 {
379 Initialize();
380 }
381
383 {
384 ThunderClap_Timer = 12000;
386 MightyBlow_Timer = 15000;
387 }
388
392
393 void Reset() override
394 {
395 _Reset();
396 Initialize();
397 }
398
399 void UpdateAI(uint32 diff) override
400 {
401 //Return since we have no target
402 if (!UpdateVictim())
403 return;
404
405 //ThunderClap_Timer
406 if (ThunderClap_Timer <= diff)
407 {
409 ThunderClap_Timer = 10000;
410 } else ThunderClap_Timer -= diff;
411
412 //FireballVolley_Timer
413 if (HealthBelowPct(51))
414 {
415 if (FireballVolley_Timer <= diff)
416 {
418 FireballVolley_Timer = 15000;
419 } else FireballVolley_Timer -= diff;
420 }
421
422 //MightyBlow_Timer
423 if (MightyBlow_Timer <= diff)
424 {
426 MightyBlow_Timer = 10000;
427 } else MightyBlow_Timer -= diff;
428 }
429 };
430};
431
432// npc_lokhtos_darkbargainer
434{
439 GOSSIP_ITEM_SHOW_ACCESS_MID = 4781, // Show me what I have access to, Lokhtos.
441};
442
443#define GOSSIP_ITEM_GET_CONTRACT "Get Thorium Brotherhood Contract" // miss in db,maybe wrong
444
446{
447 public:
448 npc_lokhtos_darkbargainer() : CreatureScript("npc_lokhtos_darkbargainer") { }
449
451 {
453
454 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
455 {
456 uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
457
458 ClearGossipMenuFor(player);
459 if (action == GOSSIP_ACTION_INFO_DEF + 1)
460 {
461 CloseGossipMenuFor(player);
463 }
464 if (action == GOSSIP_ACTION_TRADE)
465 player->GetSession()->SendListInventory(me->GetGUID());
466
467 return true;
468 }
469
470 bool OnGossipHello(Player* player) override
471 {
473 if (me->IsQuestGiver())
474 player->PrepareQuestMenu(me->GetGUID());
475
476 if (me->IsVendor() && player->GetReputationRank(59) >= REP_FRIENDLY)
478
482 {
484 }
485
486 if (player->GetReputationRank(59) < REP_FRIENDLY)
487 SendGossipMenuFor(player, 3673, me->GetGUID());
488 else
489 SendGossipMenuFor(player, 3677, me->GetGUID());
490
491 return true;
492 }
493 };
494
495 CreatureAI* GetAI(Creature* creature) const override
496 {
497 return GetBlackrockDepthsAI<npc_lokhtos_darkbargainerAI>(creature);
498 }
499};
500
501// npc_rocknot
503{
505 QUEST_ALE = 4295,
507 PATH_ESCORT_ROCKNOT = 76026
509
511{
512public:
513 npc_rocknot() : CreatureScript("npc_rocknot") { }
514
515 struct npc_rocknotAI : public EscortAI
516 {
517 npc_rocknotAI(Creature* creature) : EscortAI(creature)
518 {
519 Initialize();
520 instance = creature->GetInstanceScript();
521 }
522
524 {
525 BreakKeg_Timer = 0;
526 BreakDoor_Timer = 0;
527 }
528
530
533
534 void Reset() override
535 {
537 return;
538
539 Initialize();
540 }
541
542 void DoGo(uint32 id, uint32 state)
543 {
545 go->SetGoState((GOState)state);
546 }
547
548 void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
549 {
550 switch (waypointId)
551 {
552 case 1:
554 break;
555 case 2:
557 break;
558 case 3:
560 break;
561 case 4:
563 break;
564 case 5:
566 BreakKeg_Timer = 2000;
567 break;
568 }
569 }
570
571 void UpdateAI(uint32 diff) override
572 {
573 if (BreakKeg_Timer)
574 {
575 if (BreakKeg_Timer <= diff)
576 {
578 BreakKeg_Timer = 0;
579 BreakDoor_Timer = 1000;
580 } else BreakKeg_Timer -= diff;
581 }
582
583 if (BreakDoor_Timer)
584 {
585 if (BreakDoor_Timer <= diff)
586 {
588 DoGo(DATA_GO_BAR_KEG_TRAP, 0); //doesn't work very well, leaving code here for future
589 //spell by trap has effect61, this indicate the bar go hostile
590
592 tmp->SetFaction(FACTION_MONSTER);
593
594 //for later, this event(s) has alot more to it.
595 //optionally, DONE can trigger bar to go hostile.
597
598 BreakDoor_Timer = 0;
599 } else BreakDoor_Timer -= diff;
600 }
601
602 EscortAI::UpdateAI(diff);
603 }
604
605 void OnQuestReward(Player* /*player*/, Quest const* quest, LootItemType /*type*/, uint32 /*item*/) override
606 {
608 return;
609
610 if (quest->GetQuestId() == QUEST_ALE)
611 {
614
616
617 //keep track of amount in instance script, returns SPECIAL if amount ok and event in progress
619 {
622
624 Start(false);
625 }
626 }
627 }
628 };
629
630 CreatureAI* GetAI(Creature* creature) const override
631 {
632 return GetBlackrockDepthsAI<npc_rocknotAI>(creature);
633 }
634};
635
637{
639 new at_ring_of_law();
640 new npc_grimstone();
641 new npc_phalanx();
643 new npc_rocknot();
644}
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
@ IN_PROGRESS
@ DONE
@ SPECIAL
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
LootItemType
Definition: LootItemType.h:24
@ TEMPSUMMON_DEAD_DESPAWN
Definition: ObjectDefines.h:69
uint32 rand32()
Definition: Random.cpp:70
@ STATE_ESCORT_ESCORTING
void AddGossipItemFor(Player *player, GossipOptionNpc optionNpc, std::string text, uint32 sender, uint32 action)
void SendGossipMenuFor(Player *player, uint32 npcTextID, ObjectGuid const &guid)
void ClearGossipMenuFor(Player *player)
void InitGossipMenuFor(Player *player, uint32 menuId)
void CloseGossipMenuFor(Player *player)
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_TRADE
@ GOSSIP_ACTION_INFO_DEF
@ EMOTE_ONESHOT_KICK
@ EMOTE_ONESHOT_ATTACK_UNARMED
@ REP_FRIENDLY
@ FACTION_MONSTER
GOState
GrimstoneTexts
@ SAY_TEXT4
@ SAY_TEXT3
@ SAY_TEXT6
@ SAY_TEXT2
@ SAY_TEXT5
@ SAY_TEXT1
void AddSC_blackrock_depths()
@ MAX_NPC_AMOUNT
@ NPC_THELDREN
@ NPC_GRIMSTONE
PhalanxSpells
@ SPELL_MIGHTYBLOW
@ SPELL_FIREBALLVOLLEY
@ SPELL_THUNDERCLAP
static constexpr uint32 PATH_ESCORT_GRIMSTONE
@ SPELL_DRUNKEN_RAGE
@ QUEST_ALE
@ PATH_ESCORT_ROCKNOT
@ SAY_GOT_BEER
@ SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND
@ QUEST_A_BINDING_CONTRACT
@ ITEM_THRORIUM_BROTHERHOOD_CONTRACT
@ ITEM_SULFURON_INGOT
@ GOSSIP_ITEM_SHOW_ACCESS_MID
@ GOSSIP_ITEM_SHOW_ACCESS_OID
uint32 RingMob[]
uint32 RingBoss[]
#define GOSSIP_ITEM_GET_CONTRACT
@ BOSS_PHALANX
@ DATA_PHALANX
@ TYPE_RING_OF_LAW
@ TYPE_BAR
@ DATA_GO_BAR_KEG
@ TYPE_LYCEUM
@ DATA_ARENA3
@ DATA_ARENA2
@ DATA_GOLEM_DOOR_S
@ DATA_GOLEM_DOOR_N
@ DATA_SF_BRAZIER_N
@ DATA_ARENA4
@ DATA_GO_BAR_KEG_TRAP
@ DATA_ARENA1
@ DATA_SF_BRAZIER_S
@ DATA_GO_BAR_DOOR
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
GameObject *const me
Definition: GameObjectAI.h:50
void HandleGameObject(ObjectGuid guid, bool open, GameObject *go=nullptr)
virtual ObjectGuid GetGuidData(uint32 type) const override
bool IsEmpty() const
Definition: ObjectGuid.h:319
void Clear()
Definition: ObjectGuid.h:286
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
bool GetQuestRewardStatus(uint32 quest_id) const
Definition: Player.cpp:16033
bool HasItemCount(uint32 item, uint32 count=1, bool inBankAlso=false) const
Definition: Player.cpp:9888
WorldSession * GetSession() const
Definition: Player.h:2101
void PrepareQuestMenu(ObjectGuid guid)
Definition: Player.cpp:14474
ReputationRank GetReputationRank(uint32 faction_id) const
Definition: Player.cpp:6497
std::unique_ptr< PlayerMenu > PlayerTalkClass
Definition: Player.h:2380
uint32 GetQuestId() const
Definition: QuestDef.h:587
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Definition: Unit.h:627
void SetVisible(bool x)
Definition: Unit.cpp:8351
bool IsAlive() const
Definition: Unit.h:1164
bool IsQuestGiver() const
Definition: Unit.h:994
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
bool IsVendor() const
Definition: Unit.h:992
bool isDead() const
Definition: Unit.h:1166
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
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:2025
void SendListInventory(ObjectGuid guid)
virtual uint32 GetData(uint32) const
Definition: ZoneScript.h:91
virtual void SetData(uint32, uint32)
Definition: ZoneScript.h:92
bool OnTrigger(Player *player, AreaTriggerEntry const *) override
GameObjectAI * GetAI(GameObject *go) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
void Start(bool isActiveAttacker=true, ObjectGuid playerGUID=ObjectGuid::Empty, Quest const *quest=nullptr, bool instantRespawn=false, bool canLoopPath=false)
bool HasEscortState(uint32 escortState)
void LoadPath(uint32 pathId)
void UpdateAI(uint32 diff) override
bool HealthBelowPct(uint32 pct) const
void WaypointReached(uint32 waypointId, uint32) override
void HandleGameObject(uint32 id, bool open)
void UpdateAI(uint32 diff) override
bool OnGossipSelect(Player *player, uint32, uint32 gossipListId) override
npc_phalanxAI(Creature *creature)
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 diff) override
npc_rocknotAI(Creature *creature)
void DoGo(uint32 id, uint32 state)
void WaypointReached(uint32 waypointId, uint32) override
void OnQuestReward(Player *, Quest const *quest, LootItemType, uint32) override