Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
zone_winterspring.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/* ScriptData
7SDName: Winterspring
8SD%Complete: Almost Completely Emptied
9SDComment: Vendor Rivern Frostwind. Quest Support 4901
10SDCategory: Winterspring
11EndScriptData */
12
13/* ContentData
14npc_rivern_frostwind
15npc_ranshalla
16go_elune_fire
17EndContentData */
18
19#include "ScriptMgr.h"
20#include "ScriptedCreature.h"
21#include "ScriptedGossip.h"
22#include "ScriptedEscortAI.h"
23#include "Player.h"
24#include "WorldSession.h"
25
26/*######
27## npc_rivern_frostwind
28######*/
29
31{
32public:
33 npc_rivern_frostwind() : CreatureScript("npc_rivern_frostwind") { }
34
35 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
36 {
37 player->PlayerTalkClass->ClearMenus();
38 if (action == GOSSIP_ACTION_TRADE)
39 player->GetSession()->SendListInventory(creature->GetGUID());
40
41 return true;
42 }
43
44 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
45 {
46 if (creature->IsQuestGiver())
47 player->PrepareQuestMenu(creature->GetGUID());
48
49 if (creature->IsVendor() && player->GetReputationRank(589) == REP_EXALTED)
51
52 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
53
54 return true;
55 }
56};
57
95
97{
98 SPELL_LIGHT_TORCH = 18953, // channeled spell by Ranshalla while waiting for the torches / altar
99};
100
108
109enum GOs
110{
113 GO_ELUNE_GEM = 177414, // is respawned in script
114 GO_ELUNE_LIGHT = 177415, // are respawned in script
115};
116
118{
120};
121
123{
124 NPC_PRIESTESS_DATA_1 = -1, // dummy member for the first priestess (right)
125 NPC_PRIESTESS_DATA_2 = -2, // dummy member for the second priestess (left)
126 DATA_MOVE_PRIESTESS = -3, // dummy member to check the priestess movement
127 DATA_EVENT_END = -4, // dummy member to indicate the event end
128
129 EVENT_RESUME = 1, // trigger rest of event
130};
131
132// DialogueHelper (imported from SD)
133
140
142{
143public:
144 // The array MUST be terminated by {0, 0, 0}
145 DialogueHelper(DialogueEntry const* dialogueArray) :
146 _dialogueArray(dialogueArray),
147 _currentEntry(NULL),
148 _actionTimer(0)
149 { }
150 // The array MUST be terminated by {0, 0, 0, 0, 0}
151
154
156 {
157 // Find textEntry
158 bool found = false;
159
160 for (DialogueEntry const* entry = _dialogueArray; entry->TextEntry; ++entry)
161 {
162 if (entry->TextEntry == textEntry)
163 {
164 _currentEntry = entry;
165 found = true;
166 break;
167 }
168 }
169
170 if (!found)
171 return;
172
174 }
175
177 {
178 if (_actionTimer)
179 {
180 if (_actionTimer <= diff)
182 else
183 _actionTimer -= diff;
184 }
185 }
186
187protected:
189 virtual void JustDidDialogueStep(int32 /*entry*/) { }
191 virtual Creature* GetSpeakerByEntry(int32 /*entry*/) { return NULL; }
192
193private:
195 {
196 // Last Dialogue Entry done?
197 if (!_currentEntry || !_currentEntry->TextEntry)
198 {
199 _actionTimer = 0;
200 return;
201 }
202
203 // Get Text, SpeakerEntry and Timer
204 int32 textEntry = _currentEntry->TextEntry;
205 uint32 sayerEntry = _currentEntry->SayerEntry;
206 _actionTimer = _currentEntry->SayTimer;
207
208 // Simulate Case
209 if (sayerEntry && textEntry >= 0)
210 {
211 // Use Speaker if directly provided
212 if (Creature* speaker = GetSpeakerByEntry(sayerEntry))
213 speaker->AI()->Talk(textEntry);
214 }
215
217
218 // Increment position
220 }
221
224
226};
227
229{
232 {NPC_RANSHALLA, 0, 0}, // start the altar channeling
236 {SAY_RANSHALLA_ALTAR_6, NPC_RANSHALLA, 4000}, // start the escort here
238 {SAY_PRIESTESS_ALTAR_8, NPC_PRIESTESS_DATA_2, 5000}, // show the gem
239 {GO_ELUNE_GEM, 0, 5000},
240 {SAY_PRIESTESS_ALTAR_9, NPC_PRIESTESS_DATA_1, 4000}, // move priestess 1 near me
241 {NPC_PRIESTESS_DATA_1, 0, 3000},
245 {SAY_PRIESTESS_ALTAR_13, NPC_PRIESTESS_DATA_1, 8000}, // summon voice and guard of elune
246 {NPC_VOICE_ELUNE, 0, 12000},
247 {SAY_VOICE_ALTAR_15, NPC_VOICE_ELUNE, 5000}, // move priestess 2 near me
248 {NPC_PRIESTESS_DATA_2, 0, 3000},
252 {SAY_PRIESTESS_ALTAR_19, NPC_PRIESTESS_DATA_1, 3000}, // move the owlbeast
253 {NPC_GUARDIAN_ELUNE, 0, 2000},
254 {SAY_PRIESTESS_ALTAR_20, NPC_PRIESTESS_DATA_1, 4000}, // move the first priestess up
255 {SAY_PRIESTESS_ALTAR_21, NPC_PRIESTESS_DATA_2, 10000}, // move second priestess up
256 {DATA_MOVE_PRIESTESS, 0, 6000}, // despawn the gem
257 {DATA_EVENT_END, 0, 2000}, // turn towards the player
259 {0, 0, 0},
260};
261
263{
264 {5515.98f, -4903.43f, 846.30f, 4.58f}, // 0 right priestess summon loc
265 {5501.94f, -4920.20f, 848.69f, 6.15f}, // 1 left priestess summon loc
266 {5497.35f, -4906.49f, 850.83f, 2.76f}, // 2 guard of elune summon loc
267 {5518.38f, -4913.47f, 845.57f, 0.00f}, // 3 right priestess move loc
268 {5510.36f, -4921.17f, 846.33f, 0.00f}, // 4 left priestess move loc
269 {5511.31f, -4913.82f, 847.17f, 0.00f}, // 5 guard of elune move loc
270 {5518.51f, -4917.56f, 845.23f, 0.00f}, // 6 right priestess second move loc
271 {5514.40f, -4921.16f, 845.49f, 0.00f} // 7 left priestess second move loc
272};
273
274/*#####
275# npc_ranshalla
276#####*/
277
279{
280public:
281 npc_ranshalla() : CreatureScript("npc_ranshalla") { }
282 bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) OVERRIDE
283 {
284 if (quest->GetQuestId() == QUEST_GUARDIANS_ALTAR)
285 {
286 creature->AI()->Talk(SAY_QUEST_START);
287 creature->setFaction(FACTION_ESCORT_A_NEUTRAL_PASSIVE);
288
289 if (npc_ranshallaAI* escortAI = dynamic_cast<npc_ranshallaAI*>(creature->AI()))
290 escortAI->Start(false, false, player->GetGUID(), quest);
291
292 return true;
293 }
294
295 return false;
296 }
298 {
299 return new npc_ranshallaAI(creature);
300 }
301
303 {
304 npc_ranshallaAI(Creature* creature) : npc_escortAI(creature),
306 {
307 Reset();
308 }
309
311
317
319 {
320 _delayTimer = 0;
321 }
322
323 // Called when the player activates the torch / altar
324 void DoContinueEscort(bool isAltarWaypoint = false)
325 {
326 me->InterruptNonMeleeSpells(false);
327
328 if (isAltarWaypoint)
330 else
332
333 _delayTimer = 2000;
334 }
335
336 // Called when Ranshalla starts to channel on a torch / altar
337 void DoChannelTorchSpell(bool isAltarWaypoint = false)
338 {
339 // Check if we are using the fire or the altar and remove the no_interact flag
340 if (isAltarWaypoint)
341 {
343 {
345 me->SetFacingToObject(go);
346 _altarGUID = go->GetGUID();
347 }
348 }
351
352 // Yell and set escort to pause
355 SetEscortPaused(true);
357 }
358
360 {
361 // Summon 2 Elune priestess and make each of them move to a different spot
362 if (Creature* priestess = me->SummonCreature(NPC_PRIESTESS_ELUNE, wingThicketLocations[0].m_positionX, wingThicketLocations[0].m_positionY, wingThicketLocations[0].m_positionZ, wingThicketLocations[0].m_orientation, TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 0))
363 {
364 priestess->GetMotionMaster()->MovePoint(0, wingThicketLocations[3].m_positionX, wingThicketLocations[3].m_positionY, wingThicketLocations[3].m_positionZ);
365 _firstPriestessGUID = priestess->GetGUID();
366 }
367 if (Creature* priestess = me->SummonCreature(NPC_PRIESTESS_ELUNE, wingThicketLocations[1].m_positionX, wingThicketLocations[1].m_positionY, wingThicketLocations[1].m_positionZ, wingThicketLocations[1].m_orientation, TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 0))
368 {
369 // Left priestess should have a distinct move point because she is the one who starts the dialogue at point reach
370 priestess->GetMotionMaster()->MovePoint(1, wingThicketLocations[4].m_positionX, wingThicketLocations[4].m_positionY, wingThicketLocations[4].m_positionZ);
371 _secondPriestessGUID = priestess->GetGUID();
372 }
373 }
374
375 void SummonedMovementInform(Creature* summoned, uint32 type, uint32 pointId)
376 {
377 if (type != POINT_MOTION_TYPE || summoned->GetEntry() != NPC_PRIESTESS_ELUNE || pointId != 1)
378 return;
379
380 // Start the dialogue when the priestess reach the altar (they should both reach the point in the same time)
382 }
383
385 {
386 switch (pointId)
387 {
388 case 3:
390 break;
391 case 10: // Cavern 1
392 case 15: // Cavern 2
393 case 20: // Cavern 3
394 case 25: // Cavern 4
395 case 36: // Cavern 5
397 break;
398 case 39:
400 SetEscortPaused(true);
401 break;
402 case 41:
403 {
404 // Search for all nearest lights and respawn them
405 std::list<GameObject*> eluneLights;
407 for (std::list<GameObject*>::const_iterator itr = eluneLights.begin(); itr != eluneLights.end(); ++itr)
408 {
409 if ((*itr)->isSpawned())
410 continue;
411
412 (*itr)->SetRespawnTime(115);
413 (*itr)->Refresh();
414 }
415
416 if (GameObject* altar = me->GetMap()->GetGameObject(_altarGUID))
417 me->SetFacingToObject(altar);
418 break;
419 }
420 case 42:
421 // Summon the 2 priestess
422 SetEscortPaused(true);
425 events.ScheduleEvent(EVENT_RESUME, 2000);
426 break;
427 case 44:
428 // Stop the escort and turn towards the altar
429 SetEscortPaused(true);
430 if (GameObject* altar = me->GetMap()->GetGameObject(_altarGUID))
431 me->SetFacingToObject(altar);
432 break;
433 }
434 }
435
437 {
438 switch (entry)
439 {
440 case NPC_RANSHALLA:
441 // Start the altar channeling
443 break;
445 SetEscortPaused(false);
446 break;
448 // make the gem respawn
450 {
451 if (gem->isSpawned())
452 break;
453
454 gem->SetRespawnTime(90);
455 gem->Refresh();
456 }
457 break;
459 // move near the escort npc
460 if (Creature* priestess = me->GetMap()->GetCreature(_firstPriestessGUID))
461 priestess->GetMotionMaster()->MovePoint(0, wingThicketLocations[6].m_positionX, wingThicketLocations[6].m_positionY, wingThicketLocations[6].m_positionZ);
462 break;
464 // summon the Guardian of Elune
465 if (Creature* guard = me->SummonCreature(NPC_GUARDIAN_ELUNE, wingThicketLocations[2].m_positionX, wingThicketLocations[2].m_positionY, wingThicketLocations[2].m_positionZ, wingThicketLocations[2].m_orientation, TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 0))
466 {
467 guard->GetMotionMaster()->MovePoint(0, wingThicketLocations[5].m_positionX, wingThicketLocations[5].m_positionY, wingThicketLocations[5].m_positionZ);
468 _guardEluneGUID = guard->GetGUID();
469 }
470 // summon the Voice of Elune
471 if (GameObject* altar = me->GetMap()->GetGameObject(_altarGUID))
472 {
473 if (Creature* voice = me->SummonCreature(NPC_VOICE_ELUNE, altar->GetPositionX(), altar->GetPositionY(), altar->GetPositionZ(), 0, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 30000))
474 _voiceEluneGUID = voice->GetGUID();
475 }
476 break;
478 // move near the escort npc and continue dialogue
479 if (Creature* priestess = me->GetMap()->GetCreature(_secondPriestessGUID))
480 {
481 priestess->AI()->Talk(SAY_PRIESTESS_ALTAR_14);
482 priestess->GetMotionMaster()->MovePoint(0, wingThicketLocations[7].m_positionX, wingThicketLocations[7].m_positionY, wingThicketLocations[7].m_positionZ);
483 }
484 break;
486 // make the voice of elune leave
487 if (Creature* guard = me->GetMap()->GetCreature(_guardEluneGUID))
488 {
489 guard->GetMotionMaster()->MovePoint(0, wingThicketLocations[2].m_positionX, wingThicketLocations[2].m_positionY, wingThicketLocations[2].m_positionZ);
490 guard->DespawnOrUnsummon(4000);
491 }
492 break;
494 // make the first priestess leave
495 if (Creature* priestess = me->GetMap()->GetCreature(_firstPriestessGUID))
496 {
497 priestess->GetMotionMaster()->MovePoint(0, wingThicketLocations[0].m_positionX, wingThicketLocations[0].m_positionY, wingThicketLocations[0].m_positionZ);
498 priestess->DespawnOrUnsummon(4000);
499 }
500 break;
502 // make the second priestess leave
503 if (Creature* priestess = me->GetMap()->GetCreature(_secondPriestessGUID))
504 {
505 priestess->GetMotionMaster()->MovePoint(0, wingThicketLocations[1].m_positionX, wingThicketLocations[1].m_positionY, wingThicketLocations[1].m_positionZ);
506 priestess->DespawnOrUnsummon(4000);
507 }
508 break;
509 case DATA_EVENT_END:
510 // Turn towards the player
511 if (Player* player = GetPlayerForEscort())
512 {
513 me->SetFacingToObject(player);
514 Talk(SAY_RANSHALLA_END_1, player);
515 }
516 break;
518 // Turn towards the altar and kneel - quest complete
519 if (GameObject* altar = me->GetMap()->GetGameObject(_altarGUID))
520 {
521 me->SetFacingToObject(altar);
522 altar->ResetDoorOrButton();
523 }
524 me->SetStandState(UNIT_STAND_STATE_KNEEL);
525 if (Player* player = GetPlayerForEscort())
526 {
527 player->GroupEventHappens(QUEST_GUARDIANS_ALTAR, me);
528 Talk(SAY_RANSHALLA_END_2, player);
529 }
530 me->DespawnOrUnsummon(4000);
531 break;
532 }
533 }
534
536 {
537 switch (entry)
538 {
539 case NPC_RANSHALLA:
540 return me;
541 case NPC_VOICE_ELUNE:
542 return me->GetMap()->GetCreature(_voiceEluneGUID);
544 return me->GetMap()->GetCreature(_firstPriestessGUID);
546 return me->GetMap()->GetCreature(_secondPriestessGUID);
547 default:
548 return NULL;
549 }
550 }
551
553 {
554 DialogueUpdate(diff);
555
556 if (_delayTimer)
557 {
558 if (_delayTimer <= diff)
559 {
560 SetEscortPaused(false);
561 _delayTimer = 0;
562 }
563 else
564 _delayTimer -= diff;
565 }
566 events.Update(diff);
567 if (events.ExecuteEvent() == EVENT_RESUME)
569
571 }
572 private:
574 };
575};
576
577/*#####
578# go_elune_fire
579#####*/
580
582{
583public:
584 go_elune_fire() : GameObjectScript("go_elune_fire") { }
586 {
587 // Check if we are using the torches or the altar
588 bool isAltar = false;
589
590 if (go->GetEntry() == GO_ELUNE_ALTAR)
591 isAltar = true;
592
593 if (Creature* ranshalla = GetClosestCreatureWithEntry(go, NPC_RANSHALLA, 10.0f))
594 {
595 if (npc_ranshalla::npc_ranshallaAI* escortAI = dynamic_cast<npc_ranshalla::npc_ranshallaAI*>(ranshalla->AI()))
596 escortAI->DoContinueEscort(isAltar);
597 }
599
600 return false;
601 }
602};
603
605{
607 new npc_ranshalla();
608 new go_elune_fire();
609}
std::int32_t int32
Definition Define.h:73
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ GOSSIP_ICON_VENDOR
Definition GossipDef.h:47
@ POINT_MOTION_TYPE
@ TEMPSUMMON_CORPSE_DESPAWN
Definition Object.h:72
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
@ FACTION_ESCORT_A_NEUTRAL_PASSIVE
Creature * GetClosestCreatureWithEntry(WorldObject *source, uint32 entry, float maxSearchRange, bool alive)
GameObject * GetClosestGameObjectWithEntry(WorldObject *source, uint32 entry, float maxSearchRange)
void GetGameObjectListWithEntryInGrid(std::list< GameObject * > &list, WorldObject *source, uint32 entry, float maxSearchRange)
#define GOSSIP_TEXT_BROWSE_GOODS
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_TRADE
@ REP_EXALTED
@ GO_FLAG_NOT_SELECTABLE
@ UNIT_STAND_STATE_KNEEL
Definition Unit.h:170
@ GAMEOBJECT_FIELD_FLAGS
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
CreatureScript(const char *name)
DialogueHelper(DialogueEntry const *dialogueArray)
DialogueEntry const * _dialogueArray
virtual Creature * GetSpeakerByEntry(int32)
Will be called to get a speaker, MUST be implemented if not used in instances.
virtual void JustDidDialogueStep(int32)
Will be called when a dialogue step was done.
DialogueEntry const * _currentEntry
void DialogueUpdate(uint32 diff)
void StartNextDialogueText(int32 textEntry)
GameObjectScript(const char *name)
uint32 GetEntry() const
Definition Object.h:125
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
bool OnGossipHello(Player *, GameObject *go) OVERRIDE
bool OnQuestAccept(Player *player, Creature *creature, Quest const *quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
int32 TextEntry
To be said text entry.
int32 SayerEntry
Entry of the mob who should say.
uint32 SayTimer
Time delay until next text of array is said (0 stops).
Creature * me
virtual void UpdateEscortAI(uint32 const diff)
Player * GetPlayerForEscort()
npc_escortAI(Creature *creature)
void SetEscortPaused(bool on)
void WaypointReached(uint32 pointId) OVERRIDE
void JustDidDialogueStep(int32 entry) OVERRIDE
Will be called when a dialogue step was done.
void SummonedMovementInform(Creature *summoned, uint32 type, uint32 pointId)
void UpdateEscortAI(const uint32 diff) OVERRIDE
Creature * GetSpeakerByEntry(int32 entry) OVERRIDE
Will be called to get a speaker, MUST be implemented if not used in instances.
void DoChannelTorchSpell(bool isAltarWaypoint=false)
void DoContinueEscort(bool isAltarWaypoint=false)
@ GO_ELUNE_LIGHT
@ GO_ELUNE_ALTAR
@ GO_ELUNE_FIRE
@ GO_ELUNE_GEM
@ SAY_RANSHALLA_END_2
@ SAY_PRIESTESS_ALTAR_16
@ SAY_PRIESTESS_ALTAR_20
@ SAY_PRIESTESS_ALTAR_14
@ SAY_REACH_TORCH
@ SAY_PRIESTESS_ALTAR_17
@ EMOTE_CHANT_SPELL
@ SAY_PRIESTESS_ALTAR_7
@ SAY_REACH_ALTAR_1
@ SAY_PRIESTESS_ALTAR_18
@ SAY_RANSHALLA_ALTAR_6
@ SAY_RANSHALLA_ALTAR_2
@ SAY_VOICE_ALTAR_15
@ SAY_RANSHALLA_END_1
@ SAY_ENTER_OWL_THICKET
@ SAY_PRIESTESS_ALTAR_13
@ SAY_PRIESTESS_ALTAR_3
@ SAY_PRIESTESS_ALTAR_8
@ SAY_PRIESTESS_ALTAR_19
@ SAY_PRIESTESS_ALTAR_11
@ SAY_PRIESTESS_ALTAR_21
@ SAY_RANSHALLA_ALTAR_1
@ SAY_QUEST_START
@ SAY_AFTER_TORCH
@ SAY_PRIESTESS_ALTAR_12
@ SAY_PRIESTESS_ALTAR_9
@ SAY_PRIESTESS_ALTAR_4
@ SAY_REACH_ALTAR_2
@ SAY_PRIESTESS_ALTAR_10
@ SAY_RANSHALLA_ALTAR_5
@ NPC_PRIESTESS_DATA_1
@ DATA_EVENT_END
@ NPC_PRIESTESS_DATA_2
@ DATA_MOVE_PRIESTESS
@ EVENT_RESUME
@ QUEST_GUARDIANS_ALTAR
@ SPELL_LIGHT_TORCH
@ NPC_RANSHALLA
@ NPC_GUARDIAN_ELUNE
@ NPC_VOICE_ELUNE
@ NPC_PRIESTESS_ELUNE
const DialogueEntry introDialogue[]
static Position wingThicketLocations[]
void AddSC_winterspring()