TrinityCore
Loading...
Searching...
No Matches
boss_nefarian.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 "blackwing_lair.h"
19#include "GameObject.h"
20#include "InstanceScript.h"
21#include "MotionMaster.h"
22#include "ObjectAccessor.h"
23#include "Player.h"
24#include "ScriptedCreature.h"
25#include "ScriptedGossip.h"
26#include "ScriptMgr.h"
27#include "TemporarySummon.h"
28
51
53{
54 // Nefarius
55 // UBRS
59 // BWL
62 // SAY_VAEL_INTRO = 14, Not used - when he corrupts Vaelastrasz
63
64 // Nefarian
81};
82
88
90{
91 NEFARIUS_PATH_2 = 11037368,
92 NEFARIUS_PATH_3 = 11037376
93};
94
100
113
115{
116 // Victor Nefarius
117 // UBRS Spells
118 SPELL_CHROMATIC_CHAOS = 16337, // Self Cast hits 10339
119 SPELL_VAELASTRASZZ_SPAWN = 16354, // Self Cast Depawn one sec after
120 // BWL Spells
124 SPELL_FEAR = 22678,
125
127
128 // Nefarian
135
136 SPELL_MAGE = 23410, // wild magic
137 SPELL_WARRIOR = 23397, // beserk
138 SPELL_DRUID = 23398, // cat form
139 SPELL_PRIEST = 23401, // corrupted healing
140 SPELL_PALADIN = 23418, // syphon blessing
141 SPELL_SHAMAN = 23425, // totems
142 SPELL_WARLOCK = 23427, // infernals
143 SPELL_HUNTER = 23436, // bow broke
144 SPELL_ROGUE = 23414, // Paralise
145 SPELL_DEATH_KNIGHT = 49576 // Death Grip
146
147// 19484
148// 22664
149// 22674
150// 22666
152
158
159Position const NefarianDrakeSpawnLoc[2] = // drakonid
160{
161 { -7591.151855f, -1204.051880f, 476.800476f, 3.0f },
162 { -7514.598633f, -1150.448853f, 476.796570f, 3.0f }
163};
164
166{
167 { -7449.763672f, -1387.816040f, 526.783691f, 3.0f }, // nefarian spawn
168 { -7535.456543f, -1279.562500f, 476.798706f, 3.0f } // nefarian move
169};
170
172
174{
176 {
177 Initialize();
178 }
179
181 {
182 _spawnedAdds = 0;
183 }
184
198
199 void JustReachedHome() override
200 {
201 Reset();
202 }
203
204 void BeginEvent(Player* target)
205 {
206 _JustEngagedWith(target);
207
209
214 me->SetImmuneToPC(false);
215 AttackStart(target);
218 //events.ScheduleEvent(EVENT_MIND_CONTROL, 30s, 35s);
220 }
221
222 void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
223 {
224 if (summon->GetEntry() != NPC_NEFARIAN && summon->GetEntry() != NPC_BONE_CONSTRUCT)
225 {
227 summon->SetHomePosition(summon->GetPosition());
228 summon->SetUninteractible(true);
231 }
232 }
233
234 void JustSummoned(Creature* summon) override
235 {
236 summons.Summon(summon);
237 }
238
239 void SetData(uint32 type, uint32 data) override
240 {
241 if ( type == 1 && data == 1)
242 {
243 me->StopMoving();
245 }
246
247 if (type == 1 && data == 2)
249 }
250
251 void DoAction(int32 param) override
252 {
253 switch (param)
254 {
257 break;
259 for (ObjectGuid const& summon : summons)
260 {
261 if (Creature* boneConstruct = ObjectAccessor::GetCreature(*me, summon))
262 if (boneConstruct->GetEntry() == NPC_BONE_CONSTRUCT && !boneConstruct->IsAlive())
263 {
264 boneConstruct->SetVisible(true);
265 boneConstruct->RemoveAllGameObjects();
266 boneConstruct->SetSpawnHealth();
267 boneConstruct->setDeathState(ALIVE);
268 boneConstruct->SetUninteractible(false);
269 boneConstruct->SetStandState(UNIT_STAND_STATE_STAND);
270 SetAggressiveStateAfter(1s, boneConstruct, true, me);
271 }
272 }
274 break;
275 default:
276 break;
277 }
278 }
279
280 void UpdateAI(uint32 diff) override
281 {
282 if (!UpdateVictim())
283 {
284 events.Update(diff);
285
286 while (uint32 eventId = events.ExecuteEvent())
287 {
288 switch (eventId)
289 {
290 case EVENT_PATH_2:
293 break;
294 case EVENT_CHAOS_1:
295 if (Creature* gyth = me->FindNearestCreature(NPC_GYTH, 75.0f, true))
296 {
297 me->SetFacingToObject(gyth);
299 }
301 break;
302 case EVENT_CHAOS_2:
304 me->SetFacingTo(1.570796f);
305 break;
306 case EVENT_SUCCESS_1:
307 if (Unit* player = me->SelectNearestPlayer(60.0f))
308 {
309 me->SetFacingToObject(player);
311 if (GameObject* portcullis1 = me->FindNearestGameObject(GO_PORTCULLIS_ACTIVE, 65.0f))
312 portcullis1->SetGoState(GO_STATE_ACTIVE);
314 portcullis2->SetGoState(GO_STATE_ACTIVE);
315 }
317 break;
318 case EVENT_SUCCESS_2:
321 break;
322 case EVENT_PATH_3:
324 break;
325 default:
326 break;
327 }
328 }
329 return;
330 }
331
332 // Only do this if we haven't spawned nefarian yet
333 if (UpdateVictim() && _spawnedAdds <= 42)
334 {
335 events.Update(diff);
336
338 return;
339
340 while (uint32 eventId = events.ExecuteEvent())
341 {
342 switch (eventId)
343 {
345 switch (urand(0, 1))
346 {
347 case 0:
349 break;
350 case 1:
351 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true))
352 DoCast(target, SPELL_SHADOWBOLT);
353 break;
354 }
357 break;
358 case EVENT_FEAR:
359 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true))
360 DoCast(target, SPELL_FEAR);
362 break;
364 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true))
367 break;
368 case EVENT_SPAWN_ADD:
369 for (uint8 i = 0; i < 2; ++i)
370 {
371 uint32 CreatureID;
372 if (urand(0, 2) == 0)
373 CreatureID = NPC_CHROMATIC_DRAKANOID;
374 else
375 CreatureID = NefarianEntry[urand(0, 4)];
376 if (Creature* dragon = me->SummonCreature(CreatureID, NefarianDrakeSpawnLoc[i]))
377 {
378 dragon->SetFaction(FACTION_DRAGONFLIGHT_BLACK);
379 dragon->AI()->AttackStart(me->GetVictim());
380 }
381
382 if (++_spawnedAdds >= 42)
383 {
384 if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianLoc[0]))
385 {
386 nefarian->setActive(true);
387 nefarian->SetFarVisible(true);
388 nefarian->SetCanFly(true);
389 nefarian->SetDisableGravity(true);
390 nefarian->CastSpell(nullptr, SPELL_SHADOWFLAME_INITIAL);
391 nefarian->SetHomePosition(NefarianLoc[1]);
392 nefarian->GetMotionMaster()->MovePoint(1, NefarianLoc[1]);
393 }
397 me->SetVisible(false);
398 return;
399 }
400 }
402 break;
403 }
404
406 return;
407 }
408 }
409 }
410
411 bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
412 {
413 if (menuId == GOSSIP_ID && gossipListId == GOSSIP_OPTION_ID)
414 {
415 CloseGossipMenuFor(player);
417 BeginEvent(player);
418 }
419 return false;
420 }
421
422private:
424};
425
426struct boss_nefarian : public BossAI
427{
429 {
430 Initialize();
431 }
432
434 {
435 _phase3 = false;
436 _despawn = false;
437 _despawnTimer = 30000;
438 _sayLowHealth = false;
439 }
440
441 void Reset() override
442 {
443 Initialize();
444 }
445
446 void JustReachedHome() override
447 {
448 _despawn = true;
449 }
450
451 void JustEngagedWith(Unit* /*who*/) override
452 {
457 //events.ScheduleEvent(EVENT_TAILLASH, 10s);
460 }
461
462 void JustDied(Unit* /*killer*/) override
463 {
464 _JustDied();
466 }
467
468 void KilledUnit(Unit* victim) override
469 {
470 if (roll_chance(20))
471 return;
472
473 Talk(SAY_SLAY, victim);
474 }
475
476 void MovementInform(uint32 type, uint32 id) override
477 {
478 if (type != POINT_MOTION_TYPE)
479 return;
480
481 if (id == 1)
482 {
483 me->SetCanFly(false);
484 me->SetDisableGravity(false);
486 if (me->GetVictim())
488 }
489 }
490
491 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
492 {
493 // Phase3 begins when health below 20 pct
494 if (!_phase3 && me->HealthBelowPctDamaged(20, damage))
495 {
496 if (TempSummon* temp = me->ToTempSummon())
497 if (Unit* owner = temp->GetSummonerUnit())
498 if (owner->IsAIEnabled())
499 owner->GetAI()->DoAction(ACTION_BONE_CONSTRUCT_START_ATTACK);
500
501 _phase3 = true;
503 }
504
505 if (!_sayLowHealth && me->HealthBelowPctDamaged(5, damage))
506 {
507 _sayLowHealth = true;
509 }
510 }
511
512 void UpdateAI(uint32 diff) override
513 {
514 if (_despawn && _despawnTimer <= diff)
515 {
517 if (TempSummon* temp = me->ToTempSummon())
518 if (Unit* owner = temp->GetSummonerUnit())
519 if (owner->IsAIEnabled())
520 owner->GetAI()->DoAction(ACTION_BONE_CONSTRUCT_DESPAWN);
521 }
522 else
523 _despawnTimer -= diff;
524
525 if (!UpdateVictim())
526 return;
527
528 if (_despawn)
529 _despawn = false;
530
531 events.Update(diff);
532
534 return;
535
536 while (uint32 eventId = events.ExecuteEvent())
537 {
538 switch (eventId)
539 {
543 break;
544 case EVENT_FEAR:
547 break;
551 break;
552 case EVENT_CLEAVE:
555 break;
556 case EVENT_TAILLASH:
557 // Cast NYI since we need a better check for behind target
560 break;
561 case EVENT_CLASSCALL:
562 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
563 switch (target->GetClass())
564 {
565 case CLASS_MAGE:
566 Talk(SAY_MAGE);
568 break;
569 case CLASS_WARRIOR:
572 break;
573 case CLASS_DRUID:
575 DoCast(target, SPELL_DRUID);
576 break;
577 case CLASS_PRIEST:
580 break;
581 case CLASS_PALADIN:
584 break;
585 case CLASS_SHAMAN:
588 break;
589 case CLASS_WARLOCK:
592 break;
593 case CLASS_HUNTER:
596 break;
597 case CLASS_ROGUE:
600 break;
604 break;
605 default:
606 break;
607 }
609 break;
610 }
611
613 return;
614 }
615 }
616
617private:
622};
623
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ FAIL
@ POINT_MOTION_TYPE
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
void CloseGossipMenuFor(Player *player)
@ CLASS_HUNTER
@ CLASS_DRUID
@ CLASS_SHAMAN
@ CLASS_PRIEST
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_DEATH_KNIGHT
@ CLASS_PALADIN
@ CLASS_ROGUE
@ FACTION_FRIENDLY
@ FACTION_DRAGONFLIGHT_BLACK
@ GO_STATE_ACTIVE
@ REACT_PASSIVE
@ UNIT_STAND_STATE_SIT_HIGH_CHAIR
Definition UnitDefines.h:48
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:49
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:42
@ UNIT_NPC_FLAG_GOSSIP
DamageEffectType
@ ALIVE
Definition Unit.h:266
@ UNIT_STATE_CASTING
Definition Unit.h:290
@ NPC_NEFARIAN
@ DATA_DRAKONID_BONES
#define RegisterBlackwingLairCreatureAI(ai_name)
@ DATA_NEFARIAN
Position const NefarianLoc[2]
NefarianGameObjects
@ GO_PORTCULLIS_TOBOSSROOMS
@ GO_PORTCULLIS_ACTIVE
NefarianSpells
@ SPELL_CLEAVE
@ SPELL_SHADOW_COMMAND
@ SPELL_VEILOFSHADOW
@ SPELL_DEATH_KNIGHT
@ SPELL_BELLOWINGROAR
@ SPELL_SHAMAN
@ SPELL_FEAR
@ SPELL_DRUID
@ SPELL_PRIEST
@ SPELL_SHADOWBOLT
@ SPELL_NEFARIANS_BARRIER
@ SPELL_CHROMATIC_CHAOS
@ SPELL_SHADOWBOLT_VOLLEY
@ SPELL_VAELASTRASZZ_SPAWN
@ SPELL_ROGUE
@ SPELL_SHADOWFLAME_INITIAL
@ SPELL_TAILLASH
@ SPELL_PALADIN
@ SPELL_SHADOWFLAME
@ SPELL_WARLOCK
@ SPELL_WARRIOR
@ SPELL_MAGE
@ SPELL_HUNTER
uint32 constexpr NefarianEntry[5]
Position const NefarianDrakeSpawnLoc[2]
NefarianPaths
@ NEFARIUS_PATH_2
@ NEFARIUS_PATH_3
NefarianSays
@ SAY_DEATH
@ SAY_PALADIN
@ SAY_XHEALTH
@ SAY_CHAOS_SPELL
@ SAY_WARRIOR
@ SAY_SHADOWFLAME
@ SAY_SUCCESS
@ SAY_PRIEST
@ SAY_DRUID
@ SAY_SHAMAN
@ SAY_GAMESBEGIN_2
@ SAY_ROGUE
@ SAY_SLAY
@ SAY_MAGE
@ SAY_GAMESBEGIN_1
@ SAY_RAISE_SKELETONS
@ SAY_RANDOM
@ SAY_HUNTER
@ SAY_DEATH_KNIGHT
@ SAY_WARLOCK
@ SAY_FAILURE
void AddSC_boss_nefarian()
NefarianEvents
@ EVENT_SUCCESS_3
@ EVENT_CHAOS_1
@ EVENT_SUCCESS_1
@ EVENT_VEILOFSHADOW
@ EVENT_CLASSCALL
@ EVENT_TAILLASH
@ EVENT_CHAOS_2
@ EVENT_SPAWN_ADD
@ EVENT_MIND_CONTROL
@ EVENT_PATH_2
@ EVENT_FEAR
@ EVENT_CLEAVE
@ EVENT_SHADOWFLAME
@ EVENT_PATH_3
@ EVENT_SUCCESS_2
@ EVENT_SHADOW_BOLT
NefarianActions
@ ACTION_BONE_CONSTRUCT_START_ATTACK
@ ACTION_BONE_CONSTRUCT_DESPAWN
NefarianCreatures
@ NPC_BLACK_DRAKANOID
@ NPC_BONE_CONSTRUCT
@ NPC_BLUE_DRAKANOID
@ NPC_CHROMATIC_DRAKANOID
@ NPC_GREEN_DRAKANOID
@ NPC_GYTH
@ NPC_BRONZE_DRAKANOID
@ NPC_RED_DRAKANOID
NefarianGossip
@ GOSSIP_OPTION_ID
@ GOSSIP_ID
InstanceScript *const instance
void _JustEngagedWith(Unit *who)
SummonList summons
EventMap events
void DoZoneInCombat()
Definition CreatureAI.h:169
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:394
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 UpdateEntry(uint32 entry, CreatureData const *data=nullptr, bool updateLevel=true)
Definition Creature.cpp:591
void Update(uint32 time)
Definition EventMap.h:77
EventId ExecuteEvent()
Definition EventMap.cpp:77
void CancelEvent(EventId eventId)
Definition EventMap.cpp:156
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
virtual bool SetBossState(uint32 id, EncounterState state)
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={})
uint32 GetEntry() const
Definition Object.h:89
void DespawnEntry(uint32 entry)
void Summon(Creature const *summon)
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
void SetVisible(bool x)
Definition Unit.cpp:8787
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3846
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10804
void SetFaction(uint32 faction) override
Definition Unit.h:887
void StopMoving(bool force=false)
Definition Unit.cpp:10753
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1013
TempSummon * ToTempSummon()
Definition Unit.h:1844
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
void SetFacingToObject(WorldObject const *object, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13394
bool SetCanFly(bool enable)
Definition Unit.cpp:13538
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:1012
bool HealthBelowPctDamaged(float pct, uint32 damage) const
Definition Unit.h:805
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 SetDisableGravity(bool disable, bool updateAnimTier=true, bool updatePlayHoverAnim=true)
Definition Unit.cpp:13440
Player * SelectNearestPlayer(float range) const
Definition Object.cpp:1584
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition Object.cpp:1544
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:1403
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1522
virtual void SetData(uint32, uint32)
Definition ZoneScript.h:100
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void ResetThreatList(Unit *who=nullptr)
void SetAggressiveStateAfter(Milliseconds timer, Creature *who=nullptr, bool startCombat=true, Creature *summoner=nullptr, StartCombatArgs const &combatArgs={ })
void MovementInform(uint32 type, uint32 id) override
void UpdateAI(uint32 diff) override
void JustDied(Unit *) override
void JustReachedHome() override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void Reset() override
void JustEngagedWith(Unit *) override
void KilledUnit(Unit *victim) override
boss_nefarian(Creature *creature)
void BeginEvent(Player *target)
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
void JustReachedHome() override
void UpdateAI(uint32 diff) override
void SummonedCreatureDies(Creature *summon, Unit *) override
boss_victor_nefarius(Creature *creature)
void DoAction(int32 param) override
void JustSummoned(Creature *summon) override
void Reset() override
void SetData(uint32 type, uint32 data) override