fix(Scripts/Karazhan): Implement Nightbane summon emote and despawn on evade (#17690)
* fix(Scripts/Karazhan): Implement summon emote and despawn on evade * missing flag
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
--
|
||||||
|
UPDATE `creature_template` SET `unit_flags` = `unit_flags`|256 WHERE `entry` = 17225;
|
||||||
@@ -15,13 +15,6 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ScriptData
|
|
||||||
SDName: Boss_Nightbane
|
|
||||||
SD%Complete: 80
|
|
||||||
SDComment: SDComment: Timers may incorrect
|
|
||||||
SDCategory: Karazhan
|
|
||||||
EndScriptData */
|
|
||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "ScriptedCreature.h"
|
#include "ScriptedCreature.h"
|
||||||
@@ -46,7 +39,7 @@ enum Spells
|
|||||||
|
|
||||||
enum Says
|
enum Says
|
||||||
{
|
{
|
||||||
EMOTE_SUMMON = 0, // Not used in script
|
EMOTE_SUMMON = 0,
|
||||||
YELL_AGGRO = 1,
|
YELL_AGGRO = 1,
|
||||||
YELL_FLY_PHASE = 2,
|
YELL_FLY_PHASE = 2,
|
||||||
YELL_LAND_PHASE = 3,
|
YELL_LAND_PHASE = 3,
|
||||||
@@ -59,6 +52,11 @@ enum Groups
|
|||||||
GROUP_FLYING = 1
|
GROUP_FLYING = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Points
|
||||||
|
{
|
||||||
|
POINT_DESPAWN = 10 // Other points used dynamically throughout the script
|
||||||
|
};
|
||||||
|
|
||||||
float IntroWay[8][3] =
|
float IntroWay[8][3] =
|
||||||
{
|
{
|
||||||
{-11053.37f, -1794.48f, 149.00f},
|
{-11053.37f, -1794.48f, 149.00f},
|
||||||
@@ -77,61 +75,45 @@ struct boss_nightbane : public BossAI
|
|||||||
{
|
{
|
||||||
_intro = true;
|
_intro = true;
|
||||||
_skeletonCount = 5;
|
_skeletonCount = 5;
|
||||||
scheduler.SetValidator([this]
|
_movePhase = 0;
|
||||||
{
|
|
||||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
_skeletonscheduler.CancelAll();
|
_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->SetSpeed(MOVE_RUN, 2.0f);
|
||||||
me->SetDisableGravity(_intro);
|
me->SetDisableGravity(_intro);
|
||||||
me->SetWalk(false);
|
me->SetWalk(false);
|
||||||
me->setActive(true);
|
me->setActive(true);
|
||||||
|
|
||||||
if (instance)
|
|
||||||
{
|
|
||||||
if (instance->GetData(DATA_NIGHTBANE) == DONE)
|
|
||||||
me->DisappearAndDie();
|
|
||||||
else
|
|
||||||
instance->SetData(DATA_NIGHTBANE, NOT_STARTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleTerraceDoors(true);
|
HandleTerraceDoors(true);
|
||||||
|
|
||||||
_flying = false;
|
_flying = false;
|
||||||
_movement = false;
|
_movement = false;
|
||||||
|
_intro = true;
|
||||||
|
Phase = 1;
|
||||||
|
_movePhase = 0;
|
||||||
|
|
||||||
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{
|
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{
|
||||||
TakeOff();
|
TakeOff();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleTerraceDoors(bool open)
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
if (instance)
|
BossAI::EnterEvadeMode(why);
|
||||||
|
me->SetDisableGravity(true);
|
||||||
|
me->SendMovementFlagUpdate();
|
||||||
|
me->GetMotionMaster()->MoveTakeoff(POINT_DESPAWN, -11013.246f, -1770.5212f, 166.50139f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleTerraceDoors(bool open)
|
||||||
{
|
{
|
||||||
instance->HandleGameObject(instance->GetGuidData(DATA_MASTERS_TERRACE_DOOR_1), open);
|
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_2), open);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* who) override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
@@ -143,7 +125,8 @@ struct boss_nightbane : public BossAI
|
|||||||
ScheduleGround();
|
ScheduleGround();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScheduleGround() {
|
void ScheduleGround()
|
||||||
|
{
|
||||||
scheduler.Schedule(30s, GROUP_GROUND, [this](TaskContext context)
|
scheduler.Schedule(30s, GROUP_GROUND, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
DoCastAOE(SPELL_BELLOWING_ROAR);
|
DoCastAOE(SPELL_BELLOWING_ROAR);
|
||||||
@@ -173,7 +156,8 @@ struct boss_nightbane : public BossAI
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScheduleFly() {
|
void ScheduleFly()
|
||||||
|
{
|
||||||
_skeletonSpawnCounter = 0;
|
_skeletonSpawnCounter = 0;
|
||||||
|
|
||||||
scheduler.Schedule(2s, GROUP_FLYING, [this](TaskContext)
|
scheduler.Schedule(2s, GROUP_FLYING, [this](TaskContext)
|
||||||
@@ -230,18 +214,21 @@ struct boss_nightbane : public BossAI
|
|||||||
if (type != POINT_MOTION_TYPE)
|
if (type != POINT_MOTION_TYPE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (id == POINT_DESPAWN)
|
||||||
|
{
|
||||||
|
me->DespawnOnEvade();
|
||||||
|
}
|
||||||
|
|
||||||
if (_intro)
|
if (_intro)
|
||||||
{
|
{
|
||||||
if (id >= 8)
|
if (id >= 8)
|
||||||
{
|
{
|
||||||
//me->SetHomePosition(IntroWay[7][0], IntroWay[7][1], IntroWay[7][2], 0);
|
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC);
|
||||||
//doesn't need home position because we have to "despawn" boss on reset
|
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
|
||||||
me->SetInCombatWithZone();
|
me->SetInCombatWithZone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MovePhase = id + 1;
|
_movePhase = id + 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +243,7 @@ struct boss_nightbane : public BossAI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id < 8)
|
if (id < 8)
|
||||||
MovePhase = id + 1;
|
_movePhase = id + 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Phase = 1;
|
Phase = 1;
|
||||||
@@ -325,9 +312,9 @@ struct boss_nightbane : public BossAI
|
|||||||
{
|
{
|
||||||
if (_intro)
|
if (_intro)
|
||||||
{
|
{
|
||||||
if (MovePhase)
|
if (_movePhase)
|
||||||
{
|
{
|
||||||
if (MovePhase >= 7)
|
if (_movePhase >= 7)
|
||||||
{
|
{
|
||||||
me->SetDisableGravity(false);
|
me->SetDisableGravity(false);
|
||||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||||
@@ -335,25 +322,26 @@ struct boss_nightbane : public BossAI
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_flying && MovePhase)
|
if (_flying && _movePhase)
|
||||||
{
|
{
|
||||||
if (MovePhase >= 7)
|
if (_movePhase >= 7)
|
||||||
{
|
{
|
||||||
me->SetDisableGravity(false);
|
me->SetDisableGravity(false);
|
||||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
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]);
|
me->GetMotionMaster()->MovePoint(8, IntroWay[7][0], IntroWay[7][1], IntroWay[7][2]);
|
||||||
}
|
}
|
||||||
else
|
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())
|
if (!UpdateVictim())
|
||||||
@@ -387,7 +375,7 @@ private:
|
|||||||
bool _flying;
|
bool _flying;
|
||||||
bool _movement;
|
bool _movement;
|
||||||
|
|
||||||
uint32 MovePhase;
|
uint32 _movePhase;
|
||||||
uint8 _skeletonCount;
|
uint8 _skeletonCount;
|
||||||
uint8 _skeletonSpawnCounter;
|
uint8 _skeletonSpawnCounter;
|
||||||
};
|
};
|
||||||
@@ -397,17 +385,16 @@ class go_blackened_urn : public GameObjectScript
|
|||||||
public:
|
public:
|
||||||
go_blackened_urn() : GameObjectScript("go_blackened_urn") { }
|
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
|
bool OnGossipHello(Player* /*player*/, GameObject* go) override
|
||||||
{
|
{
|
||||||
if (InstanceScript* instance = go->GetInstanceScript())
|
if (InstanceScript* instance = go->GetInstanceScript())
|
||||||
{
|
{
|
||||||
if (instance->GetData(DATA_NIGHTBANE) != DONE && !go->FindNearestCreature(NPC_NIGHTBANE, 40.0f))
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user