TrinityCore
Loading...
Searching...
No Matches
boss_lurker_below.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/*
19 * Combat timers requires to be revisited, seems like emerge and spout timers are randomized
20 * Everything related to emerge and submerge requires sniff verification
21 * SPELL_LURKER_SPAWN_TRIGGER interrupts fishing, this closes loot window
22 * Verify if Lurker should emerge if all nagas are killed
23 */
24
25#include "ScriptMgr.h"
26#include "GameObject.h"
27#include "GameObjectAI.h"
28#include "InstanceScript.h"
29#include "Map.h"
30#include "MotionMaster.h"
31#include "Player.h"
32#include "ScriptedCreature.h"
33#include "serpent_shrine.h"
34#include "SpellAuraEffects.h"
35#include "SpellInfo.h"
36#include "SpellScript.h"
37
43
45{
46 // Combat
47 SPELL_GEYSER = 37478,
48 SPELL_WHIRL = 37660,
49 SPELL_SPOUT = 37431,
51
52 // Submerge
55
56 // World Trigger (Not Immune PC)
58
59 // Coilfang Ambusher
60 SPELL_SHOOT = 37770,
62
63 // Coilfang Guardian
66
67 // Scripts
69 SPELL_SPOUT_RIGHT = 37430
70};
71
86
99
112
118
119static Position const LurkerSpawnPosition = { 38.4567f, -417.324f, -18.9167f, 2.94961f };
120
133
134// 21217 - The Lurker Below
136{
138
139 void InitializeAI() override
140 {
143 }
144
145 void JustAppeared() override
146 {
149 }
150
161
162 void OnSpellStart(SpellInfo const* spellInfo) override
163 {
165 if (spellInfo->Id == SPELL_SPOUT)
166 {
169 }
170 }
171
172 void DoAction(int32 action) override
173 {
174 if (action == ACTION_SPOUT_STARTED)
176 }
177
178 void EnterEvadeMode(EvadeReason /*why*/) override
179 {
181 me->GetMap()->SpawnGroupDespawn(group);
182
185
186 }
187
188 void JustDied(Unit* /*killer*/) override
189 {
190 _JustDied();
191
193 me->GetMap()->SpawnGroupDespawn(group);
194 }
195
196 void UpdateAI(uint32 diff) override
197 {
198 if (!UpdateVictim())
199 return;
200
201 events.Update(diff);
202
204 return;
205
206 while (uint32 eventId = events.ExecuteEvent())
207 {
208 switch (eventId)
209 {
212 break;
213 case EVENT_GEYSER:
215 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
216 DoCast(target, SPELL_GEYSER);
217 events.Repeat(10s, 15s);
218 break;
219 case EVENT_WHIRL:
222 events.Repeat(15s, 20s);
223 break;
224 case EVENT_SPOUT:
226 events.Repeat(55s);
227 break;
232 break;
236 break;
237 case EVENT_WATER_BOLT:
241 events.Repeat(1200ms);
242 break;
243 case EVENT_SUBMERGE:
248
250 me->GetMap()->SpawnGroupSpawn(group, true, true);
251
253 me->SetUninteractible(true);
255
261 break;
262 case EVENT_EMERGE:
266 break;
267 case EVENT_EMERGE_2:
268 me->SetUninteractible(false);
270 break;
271 case EVENT_EMERGE_3:
277 break;
278 default:
279 break;
280 }
281
283 return;
284 }
285 }
286};
287
288// 21865 - Coilfang Ambusher
290{
292
293 void JustAppeared() override
294 {
295 me->GetMotionMaster()->MovePath(GetPathId(), false);
296 }
297
298 void Reset() override
299 {
301 }
302
304 {
305 if (me->HasStringId("CoilfangAmbusher1"))
307 else if (me->HasStringId("CoilfangAmbusher2"))
309 else if (me->HasStringId("CoilfangAmbusher3"))
311 else if (me->HasStringId("CoilfangAmbusher4"))
313 else if (me->HasStringId("CoilfangAmbusher5"))
315 else if (me->HasStringId("CoilfangAmbusher6"))
317 return 0;
318 }
319
320 void JustEngagedWith(Unit* /*who*/) override
321 {
322 if (roll_chance(25))
324
326 .Schedule(0s, [this](TaskContext& task)
327 {
328 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
329 DoCast(target, SPELL_SHOOT);
330 task.Repeat(3600ms, 7200ms);
331 })
332 .Schedule(10s, 15s, [this](TaskContext& task)
333 {
335 task.Repeat(10s, 20s);
336 });
337 }
338
339 void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) override
340 {
341 me->SetImmuneToPC(false);
342 SetCombatMovement(false);
344 }
345
346 void UpdateAI(uint32 diff) override
347 {
348 if (!UpdateVictim())
349 return;
350
351 _scheduler.Update(diff);
352 }
353
354private:
356};
357
358// 21873 - Coilfang Guardian
360{
362
363 void JustAppeared() override
364 {
365 me->GetMotionMaster()->MovePath(GetPathId(), false);
366 }
367
368 void Reset() override
369 {
371 }
372
374 {
375 if (me->HasStringId("CoilfangGuardian1"))
377 else if (me->HasStringId("CoilfangGuardian2"))
379 else if (me->HasStringId("CoilfangGuardian3"))
381 return 0;
382 }
383
384 void JustEngagedWith(Unit* /*who*/) override
385 {
386 if (roll_chance(25))
388
390 .Schedule(10s, 15s, [this](TaskContext& task)
391 {
393 task.Repeat(15s, 20s);
394 })
395 .Schedule(5s, 10s, [this](TaskContext& task)
396 {
398 task.Repeat(10s, 15s);
399 });
400 }
401
402 void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) override
403 {
404 me->SetImmuneToPC(false);
406 }
407
408 void UpdateAI(uint32 diff) override
409 {
410 if (!UpdateVictim())
411 return;
412
413 _scheduler.Update(diff);
414 }
415
416private:
418};
419
420// 184956 - Strange Pool
422{
424
425 bool OnGossipHello(Player* player) override
426 {
427 if (roll_chance(25))
428 {
430 trigger->CastSpell(player, SPELL_LURKER_SPAWN_TRIGGER);
431
433
435 if (InstanceScript* instance = me->GetInstanceScript())
436 instance->SetBossState(BOSS_THE_LURKER_BELOW, SPECIAL);
437 }
438
439 return false;
440 }
441};
442
443// 37431 - Spout
445{
446 bool Validate(SpellInfo const* /*spellInfo*/) override
447 {
449 }
450
451 void HandleScript(SpellEffIndex /*effIndex*/)
452 {
453 if (Creature* creature = GetCaster()->ToCreature())
454 {
455 creature->CastSpell(creature, RAND(SPELL_SPOUT_LEFT, SPELL_SPOUT_RIGHT), true);
456 creature->AI()->DoAction(ACTION_SPOUT_STARTED);
457 }
458 }
459
464};
465
466// 37429 - Spout
467// 37430 - Spout
469{
470 bool Validate(SpellInfo const* spellInfo) override
471 {
472 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValueAsInt()) });
473 }
474
475 void OnPeriodic(AuraEffect const* aurEff)
476 {
477 Unit* target = GetTarget();
478
479 float orientation = target->GetOrientation();
480
481 switch (GetId())
482 {
483 case SPELL_SPOUT_LEFT:
484 orientation += 5 * float(M_PI) / 180;
485 break;
487 orientation -= 5 * float(M_PI) / 180;
488 break;
489 default:
490 break;
491 }
492
493 target->SetFacingTo(orientation);
494
495 target->CastSpell(target, aurEff->GetAmountAsInt(), true);
496 }
497
502};
503
504// 37433 - Spout
506{
507 void FilterTargets(std::list<WorldObject*>& targets)
508 {
509 targets.remove_if([](WorldObject* target)
510 {
511 return !target->IsUnit() || target->ToUnit()->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING);
512 });
513 }
514
519};
520
#define M_PI
Definition Common.h:118
First const & RAND(First const &first, Second const &second, Rest const &... rest)
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ FAIL
@ SPECIAL
@ MOVEMENTFLAG_SWIMMING
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
Creature * GetClosestCreatureWithEntry(WorldObject *source, uint32 entry, float maxSearchRange, bool alive=true)
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_SCRIPT_EFFECT
@ TARGET_UNIT_CONE_ENEMY_24
#define EFFECT_ALL
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
@ SPELLVALUE_MAX_TARGETS
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
EvadeReason
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_SUBMERGED
Definition UnitDefines.h:51
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:42
@ UNIT_STATE_CASTING
Definition Unit.h:290
static Position const LurkerSpawnPosition
@ EVENT_SPOUT
@ EVENT_EMERGE_2
@ EVENT_EMERGE
@ EVENT_WATER_BOLT
@ EVENT_SPOUT_END_1
@ EVENT_WHIRL
@ EVENT_SPOUT_END_2
@ EVENT_EMERGE_3
@ EVENT_SUBMERGE
@ EVENT_GEYSER
@ EVENT_AGGRO_DELAY
static constexpr std::array< uint32, 9 > CoilfangNagaSpawnGroupsData
void AddSC_boss_the_lurker_below()
LurkerSpawnGroups
@ SPAWN_GROUP_COILFANG_AMBUSHER_5
@ SPAWN_GROUP_COILFANG_AMBUSHER_6
@ SPAWN_GROUP_COILFANG_GUARDIAN_3
@ SPAWN_GROUP_COILFANG_GUARDIAN_2
@ SPAWN_GROUP_COILFANG_AMBUSHER_2
@ SPAWN_GROUP_COILFANG_AMBUSHER_4
@ SPAWN_GROUP_COILFANG_GUARDIAN_1
@ SPAWN_GROUP_COILFANG_AMBUSHER_3
@ SPAWN_GROUP_COILFANG_AMBUSHER_1
@ PATH_COILFANG_AMBUSHER_5
@ PATH_COILFANG_AMBUSHER_4
@ PATH_COILFANG_AMBUSHER_6
@ PATH_COILFANG_GUARDIAN_2
@ PATH_COILFANG_AMBUSHER_2
@ PATH_COILFANG_AMBUSHER_1
@ PATH_COILFANG_GUARDIAN_3
@ PATH_COILFANG_GUARDIAN_1
@ PATH_COILFANG_AMBUSHER_3
@ SPELL_SPREAD_SHOT
@ SPELL_HAMSTRING
@ SPELL_CLEAR_ALL_DEBUFFS
@ SPELL_SHOOT
@ SPELL_WATER_BOLT
@ SPELL_SPOUT_RIGHT
@ SPELL_SPOUT
@ SPELL_SUBMERGE_VISUAL
@ SPELL_ARCING_SMASH
@ SPELL_SPOUT_LEFT
@ SPELL_WHIRL
@ SPELL_LURKER_SPAWN_TRIGGER
@ SPELL_GEYSER
@ ACTION_SPOUT_STARTED
@ NPC_WORLD_TRIGGER_NOT_IMMUNE_PC
@ SAY_AGGRO
@ EMOTE_SPOUT
int32 GetAmountAsInt() const
HookList< EffectPeriodicHandler > OnEffectPeriodic
Unit * GetTarget() const
uint32 GetId() const
bool IsUnit() const
Definition BaseEntity.h:171
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
EventMap events
void DoZoneInCombat()
Definition CreatureAI.h:169
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void SetImmuneToPC(bool apply) override
Definition Creature.h:190
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
bool HasStringId(std::string_view id) const
ReactStates GetReactState() const
Definition Creature.h:181
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
EventId ExecuteEvent()
Definition EventMap.cpp:77
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:56
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
GameObject *const me
GameObjectAI(GameObject *go, uint32 scriptId={}) noexcept
void ActivateObject(GameObjectActions action, int32 param, WorldObject *spellCaster=nullptr, uint32 spellId=0, int32 effectIndex=-1)
virtual bool SetBossState(uint32 id, EncounterState state)
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn=false, bool force=false, std::vector< WorldObject * > *spawnedObjects=nullptr)
Definition Map.cpp:2360
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty, SmoothPhasingInfo const *smoothPhasingInfo=nullptr)
Definition Object.cpp:1191
bool SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes=false, size_t *count=nullptr)
Definition Map.cpp:2449
void MovePath(uint32 pathId, bool repeatable, Optional< Milliseconds > duration={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< std::pair< Milliseconds, Milliseconds > > waitTimeRangeAtPathEnd={}, Optional< float > wanderDistanceAtPathEnds={}, Optional< bool > followPathBackwardsFromEndToStart={}, Optional< bool > exactSplinePath={}, bool generatePath=true, Optional< MovementFadeObject > fadeObject={}, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
Unit * ToUnit()
Definition Object.h:116
int32 CalcValueAsInt(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
uint32 const Id
Definition SpellInfo.h:328
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:590
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Unit * GetCaster() const
HookList< EffectHandler > OnEffectHit
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
TaskContext & Repeat(TaskScheduler::duration_t duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & Update()
Update the scheduler to the current time.
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
virtual void InitializeAI()
Definition UnitAI.cpp:35
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
bool IsWithinMeleeRange(Unit const *obj) const
Definition Unit.h:722
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10804
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
Unit * GetVictim() const
Definition Unit.h:738
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
bool HasUnitMovementFlag(MovementFlags f) const
Definition Unit.h:1761
void RemoveAllAuras()
Definition Unit.cpp:4400
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
Map * GetMap() const
Definition Object.h:411
InstanceScript * GetInstanceScript() const
Definition Object.cpp:394
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *spellInfo) override
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
#define RegisterSerpentshrineCavernGameObjectAI(ai_name)
@ NPC_THE_LURKER_BELOW
@ BOSS_THE_LURKER_BELOW
#define RegisterSerpentshrineCavernCreatureAI(ai_name)
constexpr float GetOrientation() const
Definition Position.h:90
void SetCombatMovement(bool allowMovement)
ScriptedAI(Creature *creature, uint32 scriptId=0) noexcept
void DoAction(int32 action) override
void EnterEvadeMode(EvadeReason) override
void UpdateAI(uint32 diff) override
void JustDied(Unit *) override
void JustEngagedWith(Unit *who) override
void OnSpellStart(SpellInfo const *spellInfo) override
boss_the_lurker_below(Creature *creature)
bool OnGossipHello(Player *player) override
void WaypointPathEnded(uint32, uint32) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void WaypointPathEnded(uint32, uint32) override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override