Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
zone_duskwood.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: Duskwood
8SD%Complete: 100
9SDComment: Quest support: 26720, 26760
10SDCategory: Duskwood
11EndScriptData */
12
13/* ContentData
14npc_lurking_potion
15npc_oliver_harris
16spell_q26720_harris_ampule
17EndContentData */
18
19#include "ScriptMgr.h"
20#include "ScriptedCreature.h"
21#include "SpellScript.h"
22#include "Player.h"
23#include "SpellInfo.h"
24#include "SpellMgr.h"
25#include "SpellAuras.h"
26#include "ObjectAccessor.h"
27
28#include <list>
29
30/*######
31## npc_lurking_potion - Quest 26720 A Curse We Cannot Lift
32######*/
33
46
47static bool PlayerHasActiveQuest(Player* player)
48{
49 if (!player)
50 return false;
51
53 return status == QUEST_STATUS_INCOMPLETE || status == QUEST_STATUS_COMPLETE;
54}
55
56static bool IsWeakenedLurkingWorgen(Creature* creature)
57{
58 if (!creature || creature->GetEntry() != NPC_LURKING_WORGEN)
59 return false;
60
61 if (creature->HealthAbovePct(20))
62 return false;
63
64 return creature->GetReactState() == REACT_PASSIVE;
65}
66
67static Creature* ResolveAmpuleTarget(Player* player, Unit* primaryTarget)
68{
69 if (!player)
70 return NULL;
71
72 if (primaryTarget)
73 if (Creature* creature = primaryTarget->ToCreature())
74 return creature;
75
76 if (Unit* selected = player->GetSelectedUnit())
77 if (Creature* creature = selected->ToCreature())
78 return creature;
79
80 if (Unit* victim = player->GetVictim())
81 if (Creature* creature = victim->ToCreature())
82 return creature;
83
84 return NULL;
85}
86
87static bool TryApplyHarrisAmpule(Player* player, Creature* creature)
88{
89 if (!player || !IsWeakenedLurkingWorgen(creature))
90 return false;
91
92 if (!PlayerHasActiveQuest(player))
93 return false;
94
96 creature->DespawnOrUnsummon(1000);
97 return true;
98}
99
101{
102public:
103 npc_lurking_potion() : CreatureScript("npc_lurking_potion") { }
104
106 {
107 return new npc_lurking_potionAI(creature);
108 }
109
111 {
113 _pounced(false), _hesitated(false), _pounceTargetGUID() { }
114
118
119 bool IsHesitating() const { return _hesitated; }
120
122 {
123 if (_hesitated || _pounced)
124 return;
125
127 }
128
130 {
131 _pounced = false;
132 _hesitated = false;
134 me->setRegeneratingHealth(true);
136 }
137
139 {
142
143 if (_hesitated)
144 {
145 me->setRegeneratingHealth(false);
146 me->SetReactState(REACT_PASSIVE);
147 me->SetHealth(me->CountPctFromMaxHealth(20));
148 }
149 else
150 {
151 _pounced = false;
153 me->setRegeneratingHealth(true);
154 me->SetReactState(REACT_AGGRESSIVE);
155 }
156 }
157
159 {
161 me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
162 }
163
165 {
166 if (_hesitated)
167 return;
168
169 _hesitated = true;
171 me->AttackStop();
172 me->setRegeneratingHealth(false);
173 me->SetReactState(REACT_PASSIVE);
174 me->GetMotionMaster()->Clear();
175 me->GetMotionMaster()->MoveIdle();
176
177 uint32 floorHealth = me->CountPctFromMaxHealth(20);
178 if (me->GetHealth() > floorHealth)
179 me->SetHealth(floorHealth);
180 }
181
182 void StartPounce(Player* player)
183 {
184 if (!player || _pounced || _hesitated)
185 return;
186
187 _pounced = true;
188 _pounceTargetGUID = player->GetGUID();
189
191 me->SetReactState(REACT_PASSIVE);
192 me->AttackStop();
193 me->CastSpell(player, SPELL_STUNNING_POUNCE, false);
194 }
195
197 {
198 if (!PlayerHasActiveQuest(player))
199 return;
200
201 _pounceTargetGUID = player->GetGUID();
202 me->SetReactState(REACT_AGGRESSIVE);
203 AttackStart(player);
204 }
205
207 {
208 if (!_pounced && !_hesitated && who->GetTypeId() == TypeID::TYPEID_PLAYER)
209 {
210 if (Player* player = who->ToPlayer())
211 {
212 if (PlayerHasActiveQuest(player) &&
213 me->IsWithinDistInMap(player, 25.0f) && me->IsWithinLOSInMap(player))
214 {
215 StartPounce(player);
216 return;
217 }
218 }
219 }
220
222 }
223
225 {
226 if (_hesitated || !_pounced)
227 return;
228
229 bool pounceComplete = (type == EFFECT_MOTION_TYPE && id == EVENT_JUMP) ||
230 (type == POINT_MOTION_TYPE && id == EVENT_CHARGE);
231 if (!pounceComplete)
232 return;
233
235 EngageQuestPlayer(player);
236 }
237
238 void DamageTaken(Unit* doneBy, uint32& damage) OVERRIDE
239 {
240 if (_hesitated)
241 {
242 damage = 0;
243 return;
244 }
245
246 if (Player* player = doneBy->GetCharmerOrOwnerPlayerOrPlayerItself())
247 {
248 if (PlayerHasActiveQuest(player))
249 {
250 if (!_pounced)
251 {
252 if (me->IsWithinDistInMap(player, 25.0f) && me->IsWithinLOSInMap(player))
253 StartPounce(player);
254 else
255 EngageQuestPlayer(player);
256 }
257 else if (me->GetReactState() == REACT_PASSIVE)
258 EngageQuestPlayer(player);
259 }
260 }
261
262 if (me->HealthBelowPctDamaged(21, damage))
263 {
264 uint32 floorHealth = me->CountPctFromMaxHealth(20);
265 if (me->GetHealth() > floorHealth)
266 damage = me->GetHealth() - floorHealth;
267 else
268 damage = 0;
269 }
270
271 if (!me->HealthAbovePct(20))
273 }
274
276 {
277 if (!_hesitated && !me->HealthAbovePct(20))
279
280 if (_hesitated)
281 return;
282
283 if (!UpdateVictim())
284 return;
285
287 }
288
289 void SpellHit(Unit* caster, SpellInfo const* spell) OVERRIDE
290 {
291 if (!_hesitated || !spell || spell->Id != SPELL_HARRIS_AMPULE)
292 return;
293
294 Player* player = caster->ToPlayer();
295 if (!player)
296 return;
297
298 TryApplyHarrisAmpule(player, me);
299 }
300 };
301};
302
303/*######
304## npc_oliver_harris - Quest 26760 Cry For The Moon
305######*/
306
325
326static Creature* FindSceneActor(Creature* ref, uint32 spawnGuid, uint32 entry)
327{
328 if (!ref)
329 return NULL;
330
331 Map* map = ref->GetMap();
332 map->RemoveCreatureRespawnTime(spawnGuid);
333
334 std::list<Creature*> creatures;
335 ref->GetCreatureListWithEntryInGrid(creatures, entry, 150.0f);
336 for (std::list<Creature*>::iterator itr = creatures.begin(); itr != creatures.end(); ++itr)
337 {
338 if ((*itr)->GetDBTableGUIDLow() == spawnGuid)
339 {
340 if (!(*itr)->IsAlive())
341 (*itr)->Respawn(true);
342 return (*itr)->IsAlive() ? *itr : NULL;
343 }
344 }
345
346 if (Creature* creature = map->GetCreature(MAKE_NEW_GUID(spawnGuid, entry, HIGHGUID_UNIT)))
347 {
348 if (!creature->IsAlive())
349 creature->Respawn(true);
350 return creature->IsAlive() ? creature : NULL;
351 }
352
353 Creature* creature = new Creature();
354 if (!creature->LoadCreatureFromDB(spawnGuid, map))
355 {
356 delete creature;
357 return NULL;
358 }
359
360 creature->SetVisible(false);
361 creature->AI()->Reset();
362 return creature;
363}
364
365static void ResetCryForTheMoonActor(Creature* actor, float x, float y, float z, float o, bool restoreStocks = false)
366{
367 if (!actor)
368 return;
369
370 Map* map = actor->GetMap();
371 if (uint32 dbGuid = actor->GetDBTableGUIDLow())
372 map->RemoveCreatureRespawnTime(dbGuid);
373
374 if (!actor->IsAlive())
375 actor->Respawn(true);
376
377 actor->CombatStop();
378 actor->StopMoving();
379 actor->GetMotionMaster()->Clear(false);
380 actor->GetMotionMaster()->MoveIdle();
381 actor->NearTeleportTo(x, y, z, o);
382
383 if (restoreStocks)
384 {
386 actor->AddAura(SPELL_WORGEN_INSTOCKS, actor);
388 }
389 else
391
392 actor->SetVisible(false);
393 actor->AI()->Reset();
394}
395
397{
398public:
399 npc_oliver_harris() : CreatureScript("npc_oliver_harris") { }
400
401 bool OnQuestAccept(Player* /*player*/, Creature* creature, Quest const* quest) OVERRIDE
402 {
403 if (!creature || !quest || quest->GetQuestId() != QUEST_CRY_FOR_THE_MOON)
404 return false;
405
407 return false;
408 }
409
411 {
412 return new npc_oliver_harrisAI(creature);
413 }
414
416 {
417 npc_oliver_harrisAI(Creature* creature) : ScriptedAI(creature), _sceneActive(false) { }
418
419 static void StartSceneImpl(Creature* questGiver)
420 {
421 if (!questGiver)
422 return;
423
424 npc_oliver_harrisAI* qgAi = CAST_AI(npc_oliver_harrisAI, questGiver->AI());
425 if (qgAi && qgAi->_sceneActive && !questGiver->IsVisible())
426 return;
427
428 if (qgAi)
429 qgAi->_sceneActive = false;
430
434
435 if (!eventOliver || !jitters || !worgen)
436 return;
437
438 ResetCryForTheMoonActor(eventOliver, -10754.7f, 338.823f, 37.3415f, 3.56867f);
439 ResetCryForTheMoonActor(jitters, -10767.1f, 330.665f, 37.6074f, 5.31068f);
440 ResetCryForTheMoonActor(worgen, -10747.4375f, 331.902496f, 37.739048f, 4.55199f, true);
441
442 eventOliver->AI()->Reset();
443 jitters->AI()->Reset();
444 worgen->AI()->Reset();
445
446 if (qgAi)
447 qgAi->_sceneActive = true;
448
449 questGiver->SetVisible(false);
450 if (Creature* masterHarris = questGiver->FindNearestCreature(NPC_MASTER_HARRIS, 60.0f))
451 masterHarris->SetVisible(false);
452
453 eventOliver->AI()->SetData(0, DATA_START_SCENE);
454 jitters->AI()->SetData(0, DATA_START_SCENE);
455 worgen->AI()->SetData(0, DATA_START_SCENE);
456 }
457
459 {
461 }
462
464 {
465 _sceneActive = false;
466 me->SetVisible(true);
467 if (Creature* masterHarris = me->FindNearestCreature(NPC_MASTER_HARRIS, 60.0f))
468 masterHarris->SetVisible(true);
469
471 -10754.7f, 338.823f, 37.3415f, 3.56867f);
473 -10767.1f, 330.665f, 37.6074f, 5.31068f);
475 -10747.4375f, 331.902496f, 37.739048f, 4.55199f, true);
476 }
477
478 void SetData(uint32 type, uint32 data) OVERRIDE
479 {
480 if (type == 0 && data == DATA_SCENE_ENDED)
481 SceneEnded();
482 }
483
484 private:
486 };
487};
488
489/*######
490## spell_q26720_harris_ampule - Quest 26720 Harris's Ampule
491######*/
492
494{
495public:
496 spell_q26720_harris_ampule() : SpellScriptLoader("spell_q26720_harris_ampule") { }
497
499 {
501
506
521
522 void HandleAmpule(SpellEffIndex /*effIndex*/)
523 {
524 Player* player = GetCaster()->ToPlayer();
525 if (!player)
526 return;
527
528 Creature* creature = GetHitCreature();
529 if (!creature)
530 creature = GetAmpuleCreatureFromCaster(player);
531
532 TryApplyHarrisAmpule(player, creature);
533 }
534
536 {
537 Player* player = GetCaster()->ToPlayer();
538 if (!player)
539 return;
540
542 }
543
552 };
553
558};
559
560/*######
561## spell_q26674_call_stalvan
562######*/
563
565{
566public:
567 spell_q26674_call_stalvan() : SpellScriptLoader("spell_q26674_call_stalvan") { }
568
570 {
572
574 {
575 Player* player = GetCaster()->ToPlayer();
576 if (!player)
577 return;
578
579 // Summon Stalvan and Tobias.
580 if (Creature* stalvan = player->SummonCreature(315, -10371.669922f, -1251.914185f, 35.9100023f, 5.536726f, TempSummonType::TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000))
581 {
582 stalvan->SetReactState(REACT_PASSIVE);
584 }
585 if (Creature* tobias = player->SummonCreature(35124, -10361.395508f, -1256.723022f, 35.859238f, 3.17049f, TempSummonType::TEMPSUMMON_TIMED_DESPAWN, 60000))
586 {
587 tobias->SetReactState(REACT_PASSIVE);
589
590 // Scale the summoned Tobias so he doesn't get instantly one-shot by Stalvan during the RP combat
591 tobias->SetLevel(32);
592 tobias->SetMaxHealth(25000);
593 tobias->SetFullHealth();
594 }
595 }
596
601 };
602
607};
608
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ POINT_MOTION_TYPE
@ EFFECT_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
@ TEMPSUMMON_TIMED_DESPAWN
Definition Object.h:70
@ TEMPSUMMON_CORPSE_TIMED_DESPAWN
Definition Object.h:73
@ HIGHGUID_UNIT
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
QuestStatus
Definition QuestDef.h:85
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:89
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:87
#define CAST_AI(a, b)
SpellEffIndex
@ EFFECT_0
@ EMOTE_STATE_NONE
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_APPLY_AURA
@ EVENT_CHARGE
@ EVENT_JUMP
SpellCastResult
@ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW
#define SpellCheckCastFn(F)
#define SpellEffectFn(F, I, N)
#define SpellCastFn(F)
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_IMMUNE_TO_NPC
Definition Unit.h:634
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_NPC_EMOTESTATE
virtual void MoveInLineOfSight(Unit *)
virtual void JustRespawned()
Definition CreatureAI.h:115
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
void Respawn(bool force=false)
uint32 GetDBTableGUIDLow() const
Definition Creature.h:445
void DespawnOrUnsummon(uint32 msTimeToDespawn=0)
ReactStates GetReactState() const
Definition Creature.h:461
bool LoadCreatureFromDB(uint32 guid, Map *map, bool addToMap=true)
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
Definition Map.h:238
Creature * GetCreature(uint64 guid)
Definition Map.cpp:3179
void RemoveCreatureRespawnTime(uint32 dbGuid)
Definition Map.cpp:3231
void Clear(bool reset=true)
static Player * GetPlayer(WorldObject const &, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
uint32 GetEntry() const
Definition Object.h:125
Creature * ToCreature()
Definition Object.h:207
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
void KilledMonsterCredit(uint32 entry, uint64 guid=0)
QuestStatus GetQuestStatus(uint32 quest_id) const
Unit * GetSelectedUnit() const
Definition Player.cpp:18385
Creature * GetHitCreature()
HookList< CastHandler > AfterCast
Unit * GetExplTargetUnit()
HookList< CheckCastHandler > OnCheckCast
HookList< EffectHandler > OnEffectHitTarget
HookList< CastHandler > OnCast
Unit * GetCaster()
SpellScriptLoader(const char *name)
virtual void SetData(uint32, uint32)
Definition UnitAI.h:128
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
virtual void Reset()
Definition UnitAI.h:120
Definition Unit.h:1367
void SetVisible(bool x)
Definition Unit.cpp:4163
bool HealthAbovePct(int32 pct) const
Definition Unit.h:1621
void CombatStop(bool includingCast=false)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Unit.cpp:2355
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
Aura * AddAura(uint32 spellId, Unit *target)
bool IsAlive() const
Definition Unit.h:2032
void NearTeleportTo(float x, float y, float z, float orientation, bool casting=false)
Definition Unit.cpp:8393
void StopMoving()
-------—End of Pet responses methods-------—
Definition Unit.cpp:5877
bool IsVisible() const
Definition Unit.cpp:4158
Unit * GetVictim() const
Definition Unit.h:1468
Map * GetMap() const
Definition Object.h:740
void GetCreatureListWithEntryInGrid(std::list< Creature * > &lList, uint32 uiEntry, float fMaxSearchRange) const
Definition Object.cpp:2841
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2801
TempSummon * SummonCreature(uint32 id, Position const &pos, TempSummonType spwtype=TempSummonType::TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime=0, uint32 vehId=0) const
Definition Object.cpp:2703
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnQuestAccept(Player *, Creature *creature, Quest const *quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
PrepareSpellScript(spell_q26674_call_stalvan_SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
PrepareSpellScript(spell_q26720_harris_ampule_SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
Creature * me
void EnterCombat(Unit *) OVERRIDE
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
void DamageTaken(Unit *doneBy, uint32 &damage) OVERRIDE
void SpellHit(Unit *caster, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void MovementInform(uint32 type, uint32 id) OVERRIDE
static void StartSceneImpl(Creature *questGiver)
void SetData(uint32 type, uint32 data) OVERRIDE
CryForTheMoon
@ QUEST_CRY_FOR_THE_MOON
@ GUID_RP_OLIVER
@ SPELL_WORGEN_INSTOCKS
@ GUID_RP_JITTERS
@ DATA_SCENE_ENDED
@ NPC_MASTER_HARRIS
@ NPC_EVENT_OLIVER_HARRIS
@ NPC_EVENT_SVEN_WORGEN
@ DATA_START_SCENE
@ GUID_RP_WORGEN
@ NPC_EVENT_JITTERS
LurkingPotion
@ SPELL_STUNNING_POUNCE
@ QUEST_A_CURSE_WE_CANNOT_LIFT
@ NPC_LURKING_WORGEN_KILL_CREDIT
@ NPC_LURKING_WORGEN
@ SPELL_HARRIS_AMPULE
@ SAY_HESITATE
static Creature * FindSceneActor(Creature *ref, uint32 spawnGuid, uint32 entry)
static void ResetCryForTheMoonActor(Creature *actor, float x, float y, float z, float o, bool restoreStocks=false)
static bool IsWeakenedLurkingWorgen(Creature *creature)
static Creature * ResolveAmpuleTarget(Player *player, Unit *primaryTarget)
static bool TryApplyHarrisAmpule(Player *player, Creature *creature)
void AddSC_duskwood()
static bool PlayerHasActiveQuest(Player *player)