From bbedb91e2ca6b82d34a2ff4030119ec40141ebb6 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Mon, 13 Nov 2023 01:39:14 -0300 Subject: [PATCH] fix(Scripts/Karazhan): Implement Nightbane summon emote and despawn on evade (#17690) * fix(Scripts/Karazhan): Implement summon emote and despawn on evade * missing flag --- .../rev_1699840779122160400.sql | 2 + .../Karazhan/boss_nightbane.cpp | 103 ++++++++---------- 2 files changed, 47 insertions(+), 58 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1699840779122160400.sql diff --git a/data/sql/updates/pending_db_world/rev_1699840779122160400.sql b/data/sql/updates/pending_db_world/rev_1699840779122160400.sql new file mode 100644 index 000000000..83ef0d526 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1699840779122160400.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `unit_flags` = `unit_flags`|256 WHERE `entry` = 17225; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp index 72ef3e5dd..fad93fe08 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -15,13 +15,6 @@ * with this program. If not, see . */ -/* ScriptData -SDName: Boss_Nightbane -SD%Complete: 80 -SDComment: SDComment: Timers may incorrect -SDCategory: Karazhan -EndScriptData */ - #include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" @@ -46,7 +39,7 @@ enum Spells enum Says { - EMOTE_SUMMON = 0, // Not used in script + EMOTE_SUMMON = 0, YELL_AGGRO = 1, YELL_FLY_PHASE = 2, YELL_LAND_PHASE = 3, @@ -59,6 +52,11 @@ enum Groups GROUP_FLYING = 1 }; +enum Points +{ + POINT_DESPAWN = 10 // Other points used dynamically throughout the script +}; + float IntroWay[8][3] = { {-11053.37f, -1794.48f, 149.00f}, @@ -77,60 +75,44 @@ struct boss_nightbane : public BossAI { _intro = true; _skeletonCount = 5; - scheduler.SetValidator([this] - { - return !me->HasUnitState(UNIT_STATE_CASTING); - }); + _movePhase = 0; } void Reset() override { BossAI::Reset(); _skeletonscheduler.CancelAll(); - if (!_intro) - { - //when boss is reset and we're past the intro - //cannot despawn, but have to move to a location where he normally is - //me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0); - Position preSpawnPosis = me->GetHomePosition(); - EnterEvadeMode(); - me->NearTeleportTo(preSpawnPosis); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - _intro = true; - Phase = 1; - MovePhase = 0; - } me->SetSpeed(MOVE_RUN, 2.0f); me->SetDisableGravity(_intro); me->SetWalk(false); me->setActive(true); - if (instance) - { - if (instance->GetData(DATA_NIGHTBANE) == DONE) - me->DisappearAndDie(); - else - instance->SetData(DATA_NIGHTBANE, NOT_STARTED); - } - HandleTerraceDoors(true); _flying = false; _movement = false; + _intro = true; + Phase = 1; + _movePhase = 0; ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{ TakeOff(); }); } + void EnterEvadeMode(EvadeReason why) override + { + BossAI::EnterEvadeMode(why); + me->SetDisableGravity(true); + me->SendMovementFlagUpdate(); + me->GetMotionMaster()->MoveTakeoff(POINT_DESPAWN, -11013.246f, -1770.5212f, 166.50139f); + } + void HandleTerraceDoors(bool open) { - if (instance) - { - instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_1), open); - instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_2), open); - } + instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_1), open); + instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_2), open); } void JustEngagedWith(Unit* who) override @@ -143,7 +125,8 @@ struct boss_nightbane : public BossAI ScheduleGround(); } - void ScheduleGround() { + void ScheduleGround() + { scheduler.Schedule(30s, GROUP_GROUND, [this](TaskContext context) { DoCastAOE(SPELL_BELLOWING_ROAR); @@ -173,7 +156,8 @@ struct boss_nightbane : public BossAI }); } - void ScheduleFly() { + void ScheduleFly() + { _skeletonSpawnCounter = 0; scheduler.Schedule(2s, GROUP_FLYING, [this](TaskContext) @@ -230,18 +214,21 @@ struct boss_nightbane : public BossAI if (type != POINT_MOTION_TYPE) return; + if (id == POINT_DESPAWN) + { + me->DespawnOnEvade(); + } + if (_intro) { if (id >= 8) { - //me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0); - //doesn't need home position because we have to "despawn" boss on reset - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->SetInCombatWithZone(); return; } - MovePhase = id + 1; + _movePhase = id + 1; return; } @@ -256,7 +243,7 @@ struct boss_nightbane : public BossAI } if (id < 8) - MovePhase = id + 1; + _movePhase = id + 1; else { Phase = 1; @@ -325,9 +312,9 @@ struct boss_nightbane : public BossAI { if (_intro) { - if (MovePhase) + if (_movePhase) { - if (MovePhase >= 7) + if (_movePhase >= 7) { me->SetDisableGravity(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); @@ -335,25 +322,26 @@ struct boss_nightbane : public BossAI } else { - me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]); + me->GetMotionMaster()->MovePoint(_movePhase, IntroWay[_movePhase][0], IntroWay[_movePhase][1], IntroWay[_movePhase][2]); } - MovePhase = 0; + _movePhase = 0; } return; } - if (_flying && MovePhase) + if (_flying && _movePhase) { - if (MovePhase >= 7) + if (_movePhase >= 7) { me->SetDisableGravity(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]); } else - me->GetMotionMaster()->MovePoint(MovePhase, IntroWay[MovePhase][0], IntroWay[MovePhase][1], IntroWay[MovePhase][2]); + me->GetMotionMaster()->MovePoint(_movePhase, IntroWay[_movePhase][0], IntroWay[_movePhase][1], IntroWay[_movePhase][2]); - MovePhase = 0; + _movePhase = 0; } if (!UpdateVictim()) @@ -387,7 +375,7 @@ private: bool _flying; bool _movement; - uint32 MovePhase; + uint32 _movePhase; uint8 _skeletonCount; uint8 _skeletonSpawnCounter; }; @@ -397,17 +385,16 @@ class go_blackened_urn : public GameObjectScript public: go_blackened_urn() : GameObjectScript("go_blackened_urn") { } - //if we summon an entity instead of using a sort of invisible entity, we could unsummon boss on reset - //right now that doesn't work because of how the urn works bool OnGossipHello(Player* /*player*/, GameObject* go) override { if (InstanceScript* instance = go->GetInstanceScript()) { if (instance->GetData(DATA_NIGHTBANE) != DONE && !go->FindNearestCreature(NPC_NIGHTBANE, 40.0f)) { - if (Creature* cr = instance->GetCreature(DATA_NIGHTBANE)) + if (Creature* nightbane = instance->GetCreature(DATA_NIGHTBANE)) { - cr->GetMotionMaster()->MovePoint(0, IntroWay[0][0], IntroWay[0][1], IntroWay[0][2]); + nightbane->GetMotionMaster()->MovePoint(0, IntroWay[0][0], IntroWay[0][1], IntroWay[0][2]); + nightbane->AI()->Talk(EMOTE_SUMMON); } } }