mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 15:58:04 +00:00
fix(Scripts/Karazhan) Nightbane take off phase handling (#18934)
* nightbane fly skip ground phase use conditional schedule takeoff instead invincibility fix and timing no need to delay ScheduleGround * (WIP) cursed boss new inro lands attack flag is not removed.. cant attack :) * fix intro, refactor fly to air, handle waypoints, air facing, urn,... * add PassiveAI header * revert removal of helper target on roof
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
--
|
||||||
|
-- FORCE_GOSSIP
|
||||||
|
UPDATE `creature_template` SET `detection_range` = 40, `type_flags` = `type_flags` | 134217728, `movementId` = 1988 WHERE `entry` = 17225;
|
||||||
|
|
||||||
|
-- Intro
|
||||||
|
DELETE FROM `waypoint_data` WHERE `id` = 172250;
|
||||||
|
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||||
|
(172250, 1, -11105.76, -1875.8998, 158.97804, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 2, -11175.097, -1857.2238, 101.00588, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 3, -11296.927, -1764.5311, 101.00588, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 4, -11258.901, -1722.3717, 101.00588, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 5, -11176.764, -1809.5985, 101.00588, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 6, -11191.107, -1889.3965, 107.89479, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 7, -11152.18, -1863.318, 101.00588, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 8, -11130.677, -1891.4235, 107.89634, NULL, 0, 2, 0, 100, 0),
|
||||||
|
(172250, 9, -11110.674, -1878.7712, 107.89686, NULL, 0, 2, 0, 100, 0);
|
||||||
|
|
||||||
|
-- Landing
|
||||||
|
DELETE FROM `waypoint_data` WHERE `id` = 172251;
|
||||||
|
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||||
|
(172251, 1, -11117.731, -1941.2609, 127.17197, NUll, 0, 2, 0, 100, 0),
|
||||||
|
(172251, 2, -11123.777, -1968.243, 125.92196, NUll, 0, 2, 0, 100, 0),
|
||||||
|
(172251, 3, -11148.344, -1972.9801, 116.69972, NUll, 0, 2, 0, 100, 0),
|
||||||
|
(172251, 4, -11161.62, -1945.7255, 103.08859, NUll, 0, 2, 0, 100, 0),
|
||||||
|
(172251, 5, -11168.009, -1922.9045, 97.39415, NUll, 0, 2, 0, 100, 0),
|
||||||
|
(172251, 6, -11162.231, -1900.3287, 94.72747, NUll, 0, 2, 0, 100, 0);
|
||||||
|
|
||||||
|
-- Nightbane helper target
|
||||||
|
UPDATE `creature_template` SET `type_flags` = `type_flags` | 134217728, `movementId` = 1693, `ScriptName` = 'npc_nightbane_helper_target' WHERE `entry` = 17260;
|
||||||
@@ -20,22 +20,23 @@
|
|||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "ScriptedCreature.h"
|
#include "ScriptedCreature.h"
|
||||||
#include "TaskScheduler.h"
|
#include "TaskScheduler.h"
|
||||||
|
#include "PassiveAI.h"
|
||||||
#include "karazhan.h"
|
#include "karazhan.h"
|
||||||
|
|
||||||
enum Spells
|
enum Spells
|
||||||
{
|
{
|
||||||
// phase 1
|
// Ground Phase
|
||||||
|
SPELL_RAIN_OF_BONES = 37098,
|
||||||
|
SPELL_SMOKING_BLAST = 37057,
|
||||||
|
SPELL_FIREBALL_BARRAGE = 30282,
|
||||||
|
SPELL_SEARING_CINDERS = 30127,
|
||||||
|
// Air Phase
|
||||||
SPELL_BELLOWING_ROAR = 39427,
|
SPELL_BELLOWING_ROAR = 39427,
|
||||||
SPELL_CLEAVE = 30131,
|
SPELL_CLEAVE = 30131,
|
||||||
SPELL_CHARRED_EARTH = 30129,
|
SPELL_CHARRED_EARTH = 30129,
|
||||||
SPELL_DISTRACTING_ASH = 30130,
|
SPELL_DISTRACTING_ASH = 30130,
|
||||||
SPELL_SMOLDERING_BREATH = 30210,
|
SPELL_SMOLDERING_BREATH = 30210,
|
||||||
SPELL_TAIL_SWEEP = 25653,
|
SPELL_TAIL_SWEEP = 25653,
|
||||||
// phase 2
|
|
||||||
SPELL_RAIN_OF_BONES = 37098,
|
|
||||||
SPELL_SMOKING_BLAST = 37057,
|
|
||||||
SPELL_FIREBALL_BARRAGE = 30282,
|
|
||||||
SPELL_SEARING_CINDERS = 30127,
|
|
||||||
SPELL_SUMMON_SKELETON = 30170
|
SPELL_SUMMON_SKELETON = 30170
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,20 +44,45 @@ enum Says
|
|||||||
{
|
{
|
||||||
EMOTE_SUMMON = 0,
|
EMOTE_SUMMON = 0,
|
||||||
YELL_AGGRO = 1,
|
YELL_AGGRO = 1,
|
||||||
YELL_FLY_PHASE = 2,
|
YELL_AIR_PHASE = 2,
|
||||||
YELL_LAND_PHASE = 3,
|
YELL_LAND_PHASE = 3,
|
||||||
EMOTE_BREATH = 4
|
EMOTE_BREATH = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Groups
|
enum Actions
|
||||||
|
{
|
||||||
|
ACTION_START_INTRO = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Phases
|
||||||
|
{
|
||||||
|
PHASE_INTRO = 0,
|
||||||
|
PHASE_GROUND = 1,
|
||||||
|
PHASE_FLY = 2,
|
||||||
|
PHASE_TRANSITION = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Groups
|
||||||
{
|
{
|
||||||
GROUP_GROUND = 0,
|
GROUP_GROUND = 0,
|
||||||
GROUP_FLYING = 1
|
GROUP_AIR = 1,
|
||||||
};
|
GROUP_LAND = 2
|
||||||
|
};
|
||||||
|
|
||||||
enum Points
|
enum Points
|
||||||
{
|
{
|
||||||
POINT_DESPAWN = 10 // Other points used dynamically throughout the script
|
POINT_INTRO_TAKE_OFF = 11,
|
||||||
|
POINT_INTRO_PRE_LAND = 8,
|
||||||
|
POINT_INTRO_LAND = 12,
|
||||||
|
POINT_PRE_FLY_EAST = 21,
|
||||||
|
POINT_PRE_FLY_SOUTH = 22,
|
||||||
|
POINT_PRE_FLY_WEST = 23,
|
||||||
|
POINT_PRE_FLY = 24,
|
||||||
|
POINT_FLY = 31,
|
||||||
|
POINT_LANDING_PRE = 41,
|
||||||
|
POINT_LANDING_WEST = 42,
|
||||||
|
POINT_PRE_LAND = 5,
|
||||||
|
POINT_LAND = 51,
|
||||||
};
|
};
|
||||||
|
|
||||||
float IntroWay[8][3] =
|
float IntroWay[8][3] =
|
||||||
@@ -71,13 +97,20 @@ float IntroWay[8][3] =
|
|||||||
{-11163.00f, -1903.00f, 91.473f}
|
{-11163.00f, -1903.00f, 91.473f}
|
||||||
}; //TODO: move to table
|
}; //TODO: move to table
|
||||||
|
|
||||||
|
Position const homePos = {-11003.7f, -1760.19f, 140.253f};
|
||||||
|
Position const introLandPos = {-11142.712f, -1891.193f, 92.25038f};
|
||||||
|
Position const preFlySouthPos = {-11193.77f, -1921.983f, 107.9845f};
|
||||||
|
Position const preFlyEastPos = {-11167.065f, -1976.3473f, 109.91183f};
|
||||||
|
Position const preFlyWestPos = {-11095.48f, -1866.5396f, 107.868996};
|
||||||
|
Position const preFlyPos = {-11154.900391f, -1850.670044f, 103.264999f};
|
||||||
|
Position const flyPos = {-11160.125f, -1870.683f, 97.73876f};
|
||||||
|
Position const landPos = {-11162.231f, -1900.3287f, 91.47627f};
|
||||||
|
|
||||||
struct boss_nightbane : public BossAI
|
struct boss_nightbane : public BossAI
|
||||||
{
|
{
|
||||||
boss_nightbane(Creature* creature) : BossAI(creature, DATA_NIGHTBANE)
|
boss_nightbane(Creature* creature) : BossAI(creature, DATA_NIGHTBANE)
|
||||||
{
|
{
|
||||||
_intro = true;
|
|
||||||
_skeletonCount = 5;
|
_skeletonCount = 5;
|
||||||
_movePhase = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
@@ -85,33 +118,37 @@ struct boss_nightbane : public BossAI
|
|||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
_skeletonscheduler.CancelAll();
|
_skeletonscheduler.CancelAll();
|
||||||
|
|
||||||
me->SetSpeed(MOVE_RUN, 2.0f);
|
_triggerCountTakeOffWhileFlying = 0;
|
||||||
me->SetDisableGravity(_intro);
|
_airPhasesCompleted = 0;
|
||||||
me->SetWalk(false);
|
|
||||||
me->setActive(true);
|
|
||||||
|
|
||||||
_flying = false;
|
me->SetSpeed(MOVE_RUN, me->GetCreatureTemplate()->speed_run);
|
||||||
_movement = false;
|
me->SetCanFly(true);
|
||||||
_intro = true;
|
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
Phase = 1;
|
me->SetReactState(REACT_PASSIVE);
|
||||||
_movePhase = 0;
|
|
||||||
|
|
||||||
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{
|
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{
|
||||||
TakeOff();
|
TriggerHealthTakeOff();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JustReachedHome() override
|
||||||
|
{
|
||||||
|
BossAI::JustReachedHome();
|
||||||
|
me->DespawnOnEvade();
|
||||||
|
}
|
||||||
|
|
||||||
void EnterEvadeMode(EvadeReason why) override
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
{
|
{
|
||||||
BossAI::EnterEvadeMode(why);
|
me->SetHomePosition(homePos);
|
||||||
|
me->SetCanFly(true);
|
||||||
me->SetDisableGravity(true);
|
me->SetDisableGravity(true);
|
||||||
me->SendMovementFlagUpdate();
|
me->SendMovementFlagUpdate();
|
||||||
me->GetMotionMaster()->MoveTakeoff(POINT_DESPAWN, -11013.246f, -1770.5212f, 166.50139f);
|
BossAI::EnterEvadeMode(why);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageEffectType, SpellSchoolMask spellSchoolMask) override
|
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageEffectType, SpellSchoolMask spellSchoolMask) override
|
||||||
{
|
{
|
||||||
if (_flying || Phase == 2)
|
if (_airPhasesCompleted < 3)
|
||||||
{
|
{
|
||||||
if (damage >= me->GetHealth())
|
if (damage >= me->GetHealth())
|
||||||
{
|
{
|
||||||
@@ -124,12 +161,31 @@ struct boss_nightbane : public BossAI
|
|||||||
void JustEngagedWith(Unit* who) override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
_intro = false;
|
|
||||||
|
|
||||||
Talk(YELL_AGGRO);
|
Talk(YELL_AGGRO);
|
||||||
ScheduleGround();
|
ScheduleGround();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoAction(int32 action) override
|
||||||
|
{
|
||||||
|
if (action == ACTION_START_INTRO)
|
||||||
|
{
|
||||||
|
me->GetMap()->LoadGrid(-11260.0f, -1771.0f); // load grid at far end of intro path
|
||||||
|
me->GetMap()->SetVisibilityRange(DEFAULT_VISIBILITY_INSTANCE + 100.0f); // see nightbane
|
||||||
|
me->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING);
|
||||||
|
_phase = PHASE_INTRO;
|
||||||
|
Talk(EMOTE_SUMMON);
|
||||||
|
scheduler.Schedule(2s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
|
me->SetDisableGravity(true);
|
||||||
|
me->GetMotionMaster()->MoveTakeoff(POINT_INTRO_TAKE_OFF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 10.0f, 13.99879f);
|
||||||
|
}).Schedule(4s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MovePath(me->GetEntry()*10, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScheduleGround()
|
void ScheduleGround()
|
||||||
{
|
{
|
||||||
scheduler.Schedule(30s, GROUP_GROUND, [this](TaskContext context)
|
scheduler.Schedule(30s, GROUP_GROUND, [this](TaskContext context)
|
||||||
@@ -169,12 +225,13 @@ struct boss_nightbane : public BossAI
|
|||||||
{
|
{
|
||||||
_skeletonSpawnCounter = 0;
|
_skeletonSpawnCounter = 0;
|
||||||
|
|
||||||
scheduler.Schedule(2s, GROUP_FLYING, [this](TaskContext)
|
scheduler.Schedule(2s, GROUP_AIR, [this](TaskContext)
|
||||||
{
|
{
|
||||||
DoResetThreatList();
|
DoResetThreatList();
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
|
||||||
{
|
{
|
||||||
_skeletonSpawnPos = target->GetPosition();
|
_skeletonSpawnPos = target->GetPosition();
|
||||||
|
me->SetFacingTo(_skeletonSpawnPos.GetOrientation());
|
||||||
me->CastSpell(_skeletonSpawnPos.GetPositionX(), _skeletonSpawnPos.GetPositionY(), _skeletonSpawnPos.GetPositionZ(), SPELL_RAIN_OF_BONES, true);
|
me->CastSpell(_skeletonSpawnPos.GetPositionX(), _skeletonSpawnPos.GetPositionY(), _skeletonSpawnPos.GetPositionZ(), SPELL_RAIN_OF_BONES, true);
|
||||||
_skeletonscheduler.Schedule(50ms, [this](TaskContext context)
|
_skeletonscheduler.Schedule(50ms, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
@@ -187,18 +244,23 @@ struct boss_nightbane : public BossAI
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).Schedule(20s, GROUP_FLYING, [this](TaskContext context)
|
}).Schedule(20s, GROUP_AIR, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
DoCastRandomTarget(SPELL_DISTRACTING_ASH);
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
||||||
|
{
|
||||||
|
me->SetFacingToObject(target);
|
||||||
|
DoCast(target, SPELL_DISTRACTING_ASH);
|
||||||
|
}
|
||||||
context.Repeat(2s); //timer wrong?
|
context.Repeat(2s); //timer wrong?
|
||||||
}).Schedule(25s, GROUP_FLYING, [this](TaskContext context)
|
}).Schedule(25s, GROUP_AIR, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
//5 seconds added due to double trigger?
|
//5 seconds added due to double trigger?
|
||||||
//trigger for timer in original + in rain of bones
|
//trigger for timer in original + in rain of bones
|
||||||
//timers need some investigation
|
//timers need some investigation
|
||||||
|
me->SetFacingToObject(me->GetVictim());
|
||||||
DoCastVictim(SPELL_SMOKING_BLAST);
|
DoCastVictim(SPELL_SMOKING_BLAST);
|
||||||
context.Repeat(1500ms); //timer wrong?
|
context.Repeat(1500ms); //timer wrong?
|
||||||
}).Schedule(13s, GROUP_FLYING, [this](TaskContext context)
|
}).Schedule(13s, GROUP_AIR, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
DoCastOnFarAwayPlayers(SPELL_FIREBALL_BARRAGE, false, 80.0f);
|
DoCastOnFarAwayPlayers(SPELL_FIREBALL_BARRAGE, false, 80.0f);
|
||||||
context.Repeat(20s);
|
context.Repeat(20s);
|
||||||
@@ -207,58 +269,135 @@ struct boss_nightbane : public BossAI
|
|||||||
|
|
||||||
void AttackStart(Unit* who) override
|
void AttackStart(Unit* who) override
|
||||||
{
|
{
|
||||||
if (!_intro && !_flying)
|
if (_phase == PHASE_GROUND)
|
||||||
ScriptedAI::AttackStart(who);
|
ScriptedAI::AttackStart(who);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* who) override
|
void MoveInLineOfSight(Unit* who) override
|
||||||
{
|
{
|
||||||
if (!_intro && !_flying)
|
if (_phase == PHASE_GROUND)
|
||||||
ScriptedAI::MoveInLineOfSight(who);
|
ScriptedAI::MoveInLineOfSight(who);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathEndReached(uint32 pathId) override
|
||||||
|
{
|
||||||
|
BossAI::PathEndReached(pathId);
|
||||||
|
if (pathId == me->GetEntry()*10) // intro
|
||||||
|
{
|
||||||
|
me->GetMap()->SetVisibilityRange(DEFAULT_VISIBILITY_INSTANCE); // restore visibility
|
||||||
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->ClearUnitState(UNIT_STATE_IGNORE_PATHFINDING);
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_INTRO_LAND, introLandPos);
|
||||||
|
me->SetSpeed(MOVE_RUN, 2.0f);
|
||||||
|
}).Schedule(3s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->SetDisableGravity(false);
|
||||||
|
me->SetCanFly(false);
|
||||||
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||||
|
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC);
|
||||||
|
_phase = PHASE_GROUND;
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
me->SetInCombatWithZone();
|
||||||
|
}).Schedule(8s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
if (!SelectTargetFromPlayerList(45.0f))
|
||||||
|
{
|
||||||
|
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (pathId == me->GetEntry()*10+1) // landing
|
||||||
|
{
|
||||||
|
_airPhasesCompleted++;
|
||||||
|
if (_triggerCountTakeOffWhileFlying > 0)
|
||||||
|
{
|
||||||
|
_triggerCountTakeOffWhileFlying--;
|
||||||
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY_SOUTH, preFlySouthPos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
DoResetThreatList();
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_LAND, landPos);
|
||||||
|
me->SetDisableGravity(false);
|
||||||
|
me->SetCanFly(false);
|
||||||
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
||||||
|
_phase = PHASE_GROUND;
|
||||||
|
ScheduleGround();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 id) override
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
{
|
{
|
||||||
if (type != POINT_MOTION_TYPE)
|
if (type != POINT_MOTION_TYPE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (id == POINT_DESPAWN)
|
switch (id)
|
||||||
{
|
{
|
||||||
me->DespawnOnEvade();
|
case POINT_INTRO_TAKE_OFF:
|
||||||
}
|
break;
|
||||||
|
case POINT_INTRO_LAND:
|
||||||
if (_intro)
|
DoStartMovement(me->GetVictim());
|
||||||
{
|
break;
|
||||||
if (id >= 8)
|
case POINT_PRE_FLY_EAST:
|
||||||
{
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC);
|
{
|
||||||
me->SetInCombatWithZone();
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY_SOUTH, preFlySouthPos);
|
||||||
return;
|
});
|
||||||
}
|
break;
|
||||||
|
case POINT_PRE_FLY_SOUTH:
|
||||||
_movePhase = id + 1;
|
case POINT_PRE_FLY_WEST:
|
||||||
return;
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
}
|
{
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY, preFlyPos);
|
||||||
if (_flying)
|
});
|
||||||
{
|
break;
|
||||||
if (id == 0)
|
case POINT_PRE_FLY:
|
||||||
{
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_FLY, flyPos);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case POINT_FLY:
|
||||||
|
_phase = PHASE_FLY;
|
||||||
Talk(EMOTE_BREATH);
|
Talk(EMOTE_BREATH);
|
||||||
_flying = false;
|
ScheduleFly();
|
||||||
Phase = 2;
|
ScheduleLand();
|
||||||
return;
|
break;
|
||||||
}
|
case POINT_LANDING_PRE:
|
||||||
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
if (id < 8)
|
{
|
||||||
_movePhase = id + 1;
|
me->GetMotionMaster()->MovePoint(POINT_LANDING_WEST, preFlyWestPos);
|
||||||
else
|
});
|
||||||
{
|
break;
|
||||||
Phase = 1;
|
case POINT_LANDING_WEST:
|
||||||
_flying = false;
|
if (_triggerCountTakeOffWhileFlying > 0)
|
||||||
_movement = true;
|
{
|
||||||
return;
|
_airPhasesCompleted++;
|
||||||
}
|
_triggerCountTakeOffWhileFlying--;
|
||||||
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY, preFlyPos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scheduler.Schedule(0s, [this](TaskContext /*context*/)
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MovePath(me->GetEntry()*10+1, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case POINT_LAND:
|
||||||
|
DoStartMovement(me->GetVictim());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,107 +423,79 @@ struct boss_nightbane : public BossAI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TakeOff()
|
void TriggerHealthTakeOff()
|
||||||
{
|
{
|
||||||
Talk(YELL_FLY_PHASE);
|
if (_phase != PHASE_GROUND)
|
||||||
|
{
|
||||||
|
_triggerCountTakeOffWhileFlying++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_phase = PHASE_TRANSITION;
|
||||||
|
Talk(YELL_AIR_PHASE);
|
||||||
scheduler.CancelGroup(GROUP_GROUND);
|
scheduler.CancelGroup(GROUP_GROUND);
|
||||||
|
|
||||||
me->InterruptSpell(CURRENT_GENERIC_SPELL);
|
me->InterruptSpell(CURRENT_GENERIC_SPELL);
|
||||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||||
me->SetDisableGravity(true);
|
me->SetDisableGravity(true);
|
||||||
|
me->SetCanFly(true);
|
||||||
|
me->SendMovementFlagUpdate();
|
||||||
|
me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
|
||||||
|
FlyToClosestPreFlyWayPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlyToClosestPreFlyWayPoint()
|
||||||
|
{
|
||||||
|
Position closestWP = preFlyPos;
|
||||||
|
if (me->GetDistance(preFlyEastPos) < me->GetDistance(closestWP))
|
||||||
|
closestWP = preFlyEastPos;
|
||||||
|
if (me->GetDistance(preFlySouthPos) < me->GetDistance(closestWP))
|
||||||
|
closestWP = preFlySouthPos;
|
||||||
|
if (me->GetDistance(preFlyWestPos) < me->GetDistance(closestWP))
|
||||||
|
closestWP = preFlyWestPos;
|
||||||
|
|
||||||
me->GetMotionMaster()->Clear(false);
|
me->GetMotionMaster()->Clear(false);
|
||||||
me->GetMotionMaster()->MovePoint(0, IntroWay[2][0], IntroWay[2][1], IntroWay[2][2]);
|
if (closestWP == preFlyPos)
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY, closestWP);
|
||||||
|
else if (closestWP == preFlyEastPos)
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY_EAST, closestWP);
|
||||||
|
else if (closestWP == preFlySouthPos)
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY_SOUTH, closestWP);
|
||||||
|
else if (closestWP == preFlyWestPos)
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PRE_FLY_WEST, closestWP);
|
||||||
|
}
|
||||||
|
|
||||||
_flying = true;
|
void ScheduleLand()
|
||||||
|
{
|
||||||
ScheduleFly();
|
scheduler.Schedule(30s, GROUP_LAND, [this](TaskContext) /*context*/
|
||||||
|
|
||||||
//handle landing again
|
|
||||||
scheduler.Schedule(45s, 60s, [this](TaskContext)
|
|
||||||
{
|
{
|
||||||
Talk(YELL_LAND_PHASE);
|
Talk(YELL_LAND_PHASE);
|
||||||
|
scheduler.CancelGroup(GROUP_AIR);
|
||||||
|
_phase = PHASE_TRANSITION;
|
||||||
|
|
||||||
me->GetMotionMaster()->Clear(false);
|
me->GetMotionMaster()->Clear(false);
|
||||||
me->GetMotionMaster()->MovePoint(3, IntroWay[3][0], IntroWay[3][1], IntroWay[3][2]);
|
me->GetMotionMaster()->MovePoint(POINT_LANDING_PRE, preFlyPos);
|
||||||
|
|
||||||
_flying = true;
|
|
||||||
scheduler.CancelGroup(GROUP_FLYING);
|
|
||||||
scheduler.Schedule(2s, [this](TaskContext)
|
|
||||||
{
|
|
||||||
ScheduleGround();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (_intro)
|
scheduler.Update(diff);
|
||||||
{
|
_skeletonscheduler.Update(diff);
|
||||||
if (_movePhase)
|
|
||||||
{
|
|
||||||
if (_movePhase >= 7)
|
|
||||||
{
|
|
||||||
me->SetDisableGravity(false);
|
|
||||||
me->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
_movePhase = 0;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_flying && _movePhase)
|
|
||||||
{
|
|
||||||
if (_movePhase >= 7)
|
|
||||||
{
|
|
||||||
me->SetDisableGravity(false);
|
|
||||||
DoResetThreatList();
|
|
||||||
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]);
|
|
||||||
|
|
||||||
_movePhase = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_flying)
|
if (_phase == PHASE_GROUND)
|
||||||
return;
|
|
||||||
|
|
||||||
scheduler.Update(diff);
|
|
||||||
_skeletonscheduler.Update(diff);
|
|
||||||
|
|
||||||
// Phase 1 "GROUND FIGHT"
|
|
||||||
if (Phase == 1)
|
|
||||||
{
|
{
|
||||||
if (_movement)
|
|
||||||
{
|
|
||||||
DoStartMovement(me->GetVictim());
|
|
||||||
_movement = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 Phase;
|
uint8 _phase;
|
||||||
|
uint8 _airPhasesCompleted;
|
||||||
|
uint8 _triggerCountTakeOffWhileFlying;
|
||||||
|
|
||||||
TaskScheduler _skeletonscheduler;
|
TaskScheduler _skeletonscheduler;
|
||||||
|
|
||||||
bool _intro;
|
|
||||||
bool _flying;
|
|
||||||
bool _movement;
|
|
||||||
|
|
||||||
uint32 _movePhase;
|
|
||||||
uint8 _skeletonCount;
|
uint8 _skeletonCount;
|
||||||
uint8 _skeletonSpawnCounter;
|
uint8 _skeletonSpawnCounter;
|
||||||
Position _skeletonSpawnPos;
|
Position _skeletonSpawnPos;
|
||||||
@@ -399,22 +510,31 @@ public:
|
|||||||
{
|
{
|
||||||
if (InstanceScript* instance = go->GetInstanceScript())
|
if (InstanceScript* instance = go->GetInstanceScript())
|
||||||
{
|
{
|
||||||
if (instance->GetData(DATA_NIGHTBANE) != DONE && !go->FindNearestCreature(NPC_NIGHTBANE, 40.0f))
|
// if (instance->GetBossState(DATA_NIGHTBANE) == NOT_STARTED || instance->GetBossState(DATA_NIGHTBANE) == FAIL)
|
||||||
|
if (instance->GetBossState(DATA_NIGHTBANE) == NOT_STARTED)
|
||||||
{
|
{
|
||||||
if (Creature* nightbane = instance->GetCreature(DATA_NIGHTBANE))
|
if (Creature* nightbane = instance->GetCreature(DATA_NIGHTBANE))
|
||||||
{
|
{
|
||||||
nightbane->GetMotionMaster()->MovePoint(0, IntroWay[0][0], IntroWay[0][1], IntroWay[0][2]);
|
if (nightbane->IsAlive())
|
||||||
nightbane->AI()->Talk(EMOTE_SUMMON);
|
{
|
||||||
|
nightbane->AI()->DoAction(ACTION_START_INTRO);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct npc_nightbane_helper_target : public NullCreatureAI
|
||||||
|
{
|
||||||
|
npc_nightbane_helper_target(Creature* creature) : NullCreatureAI(creature) { me->SetDisableGravity(true); }
|
||||||
|
};
|
||||||
|
|
||||||
void AddSC_boss_nightbane()
|
void AddSC_boss_nightbane()
|
||||||
{
|
{
|
||||||
RegisterKarazhanCreatureAI(boss_nightbane);
|
RegisterKarazhanCreatureAI(boss_nightbane);
|
||||||
new go_blackened_urn();
|
new go_blackened_urn();
|
||||||
|
RegisterKarazhanCreatureAI(npc_nightbane_helper_target);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user