fb44221203
Port From (https://github.com/TrinityCore/TrinityCore/commit/88ff97c1f96381565c47f8ca1993bdc7fce19fd6)
372 lines
14 KiB
C#
372 lines
14 KiB
C#
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
|
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
|
|
|
using Framework.Constants;
|
|
using Game.AI;
|
|
using Game.Entities;
|
|
using Game.Maps;
|
|
using Game.Scripting;
|
|
using Game.Spells;
|
|
using System;
|
|
|
|
namespace Scripts.EasternKingdoms.Karazhan.Nightbane
|
|
{
|
|
struct SpellIds
|
|
{
|
|
public const uint BellowingRoar = 36922;
|
|
public const uint CharredEarth = 30129;
|
|
public const uint Cleave = 30131;
|
|
public const uint DistractingAsh = 30130;
|
|
public const uint RainOfBones = 37098;
|
|
public const uint SmokingBlast = 30128;
|
|
public const uint SmokingBlastT = 37057;
|
|
public const uint SmolderingBreath = 30210;
|
|
public const uint SummonSkeleton = 30170;
|
|
public const uint TailSweep = 25653;
|
|
}
|
|
|
|
struct TextIds
|
|
{
|
|
public const uint EmoteSummon = 0;
|
|
public const uint YellAggro = 1;
|
|
public const uint YellFlyPhase = 2;
|
|
public const uint YellLandPhase = 3;
|
|
public const uint EmoteBreath = 4;
|
|
}
|
|
|
|
struct PointIds
|
|
{
|
|
public const uint IntroStart = 0;
|
|
public const uint IntroEnd = 1;
|
|
public const uint IntroLanding = 2;
|
|
public const uint PhaseTwoFly = 3;
|
|
public const uint PhaseTwoPreFly = 4;
|
|
public const uint PhaseTwoLanding = 5;
|
|
public const uint PhaseTwoEnd = 6;
|
|
}
|
|
|
|
struct SplineChainIds
|
|
{
|
|
public const uint IntroStart = 1;
|
|
public const uint IntroEnd = 2;
|
|
public const uint IntroLanding = 3;
|
|
public const uint SecondLanding = 4;
|
|
public const uint PhaseTwo = 5;
|
|
}
|
|
|
|
enum NightbanePhases
|
|
{
|
|
Intro = 0,
|
|
Ground,
|
|
Fly
|
|
}
|
|
|
|
struct MiscConst
|
|
{
|
|
public const int ActionSummon = 0;
|
|
public const uint PathPhaseTwo = 13547500;
|
|
|
|
public const uint GroupGround = 1;
|
|
public const uint GroupFly = 2;
|
|
|
|
public static Position FlyPosition = new Position(-11160.13f, -1870.683f, 97.73876f, 0.0f);
|
|
public static Position FlyPositionLeft = new Position(-11094.42f, -1866.992f, 107.8375f, 0.0f);
|
|
public static Position FlyPositionRight = new Position(-11193.77f, -1921.983f, 107.9845f, 0.0f);
|
|
}
|
|
|
|
[Script]
|
|
class boss_nightbane : BossAI
|
|
{
|
|
byte _flyCount;
|
|
NightbanePhases phase;
|
|
|
|
public boss_nightbane(Creature creature) : base(creature, DataTypes.Nightbane) { }
|
|
|
|
public override void Reset()
|
|
{
|
|
_Reset();
|
|
_flyCount = 0;
|
|
me.SetDisableGravity(true);
|
|
HandleTerraceDoors(true);
|
|
GameObject urn = ObjectAccessor.GetGameObject(me, instance.GetGuidData(DataTypes.GoBlackenedUrn));
|
|
if (urn)
|
|
urn.RemoveFlag(GameObjectFlags.InUse);
|
|
}
|
|
|
|
public override void EnterEvadeMode(EvadeReason why)
|
|
{
|
|
me.SetDisableGravity(true);
|
|
base.EnterEvadeMode(why);
|
|
}
|
|
|
|
public override void JustReachedHome()
|
|
{
|
|
_DespawnAtEvade();
|
|
}
|
|
|
|
public override void JustDied(Unit killer)
|
|
{
|
|
_JustDied();
|
|
HandleTerraceDoors(true);
|
|
}
|
|
|
|
public override void DoAction(int action)
|
|
{
|
|
if (action == MiscConst.ActionSummon)
|
|
{
|
|
Talk(TextIds.EmoteSummon);
|
|
phase = NightbanePhases.Intro;
|
|
me.SetActive(true);
|
|
me.SetFarVisible(true);
|
|
me.SetUninteractible(false);
|
|
me.GetMotionMaster().MoveAlongSplineChain(PointIds.IntroStart, SplineChainIds.IntroStart, false);
|
|
HandleTerraceDoors(false);
|
|
}
|
|
}
|
|
|
|
void SetupGroundPhase()
|
|
{
|
|
phase = NightbanePhases.Ground;
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(15), MiscConst.GroupGround, task =>
|
|
{
|
|
DoCastVictim(SpellIds.Cleave);
|
|
task.Repeat(TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(15));
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(23), MiscConst.GroupGround, task =>
|
|
{
|
|
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
|
|
if (target)
|
|
if (!me.HasInArc(MathF.PI, target))
|
|
DoCast(target, SpellIds.TailSweep);
|
|
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30));
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(48), MiscConst.GroupGround, task =>
|
|
{
|
|
DoCastAOE(SpellIds.BellowingRoar);
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(18), MiscConst.GroupGround, task =>
|
|
{
|
|
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
|
|
if (target)
|
|
DoCast(target, SpellIds.CharredEarth);
|
|
task.Repeat(TimeSpan.FromSeconds(18), TimeSpan.FromSeconds(21));
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(26), TimeSpan.FromSeconds(30), MiscConst.GroupGround, task =>
|
|
{
|
|
DoCastVictim(SpellIds.SmolderingBreath);
|
|
task.Repeat(TimeSpan.FromSeconds(28), TimeSpan.FromSeconds(40));
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(82), MiscConst.GroupGround, task =>
|
|
{
|
|
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
|
|
if (target)
|
|
DoCast(target, SpellIds.DistractingAsh);
|
|
});
|
|
}
|
|
|
|
void HandleTerraceDoors(bool open)
|
|
{
|
|
instance.HandleGameObject(instance.GetGuidData(DataTypes.MastersTerraceDoor1), open);
|
|
instance.HandleGameObject(instance.GetGuidData(DataTypes.MastersTerraceDoor2), open);
|
|
}
|
|
|
|
public override void JustEngagedWith(Unit who)
|
|
{
|
|
base.JustEngagedWith(who);
|
|
Talk(TextIds.YellAggro);
|
|
SetupGroundPhase();
|
|
}
|
|
|
|
public override void DamageTaken(Unit attacker, ref uint damage, DamageEffectType damageType, SpellInfo spellInfo = null)
|
|
{
|
|
if (phase == NightbanePhases.Fly)
|
|
{
|
|
if (damage >= me.GetHealth())
|
|
damage = (uint)(me.GetHealth() - 1);
|
|
return;
|
|
}
|
|
|
|
if ((_flyCount == 0 && HealthBelowPct(75)) || (_flyCount == 1 && HealthBelowPct(50)) || (_flyCount == 2 && HealthBelowPct(25)))
|
|
{
|
|
phase = NightbanePhases.Fly;
|
|
StartPhaseFly();
|
|
}
|
|
}
|
|
|
|
public override void MovementInform(MovementGeneratorType type, uint pointId)
|
|
{
|
|
if (type == MovementGeneratorType.SplineChain)
|
|
{
|
|
switch (pointId)
|
|
{
|
|
case PointIds.IntroStart:
|
|
me.SetStandState(UnitStandStateType.Stand);
|
|
_scheduler.Schedule(TimeSpan.FromMilliseconds(1), task =>
|
|
{
|
|
me.GetMotionMaster().MoveAlongSplineChain(PointIds.IntroEnd, SplineChainIds.IntroEnd, false);
|
|
});
|
|
break;
|
|
case PointIds.IntroEnd:
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(2), task =>
|
|
{
|
|
me.GetMotionMaster().MoveAlongSplineChain(PointIds.IntroLanding, SplineChainIds.IntroLanding, false);
|
|
});
|
|
break;
|
|
case PointIds.IntroLanding:
|
|
me.SetDisableGravity(false);
|
|
me.HandleEmoteCommand(Emote.OneshotLand);
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(3), task =>
|
|
{
|
|
me.SetImmuneToPC(false);
|
|
DoZoneInCombat();
|
|
});
|
|
break;
|
|
case PointIds.PhaseTwoLanding:
|
|
phase = NightbanePhases.Ground;
|
|
me.SetDisableGravity(false);
|
|
me.HandleEmoteCommand(Emote.OneshotLand);
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(3), task =>
|
|
{
|
|
SetupGroundPhase();
|
|
me.SetReactState(ReactStates.Aggressive);
|
|
});
|
|
break;
|
|
case PointIds.PhaseTwoEnd:
|
|
_scheduler.Schedule(TimeSpan.FromMilliseconds(1), task =>
|
|
{
|
|
me.GetMotionMaster().MoveAlongSplineChain(PointIds.PhaseTwoLanding, SplineChainIds.SecondLanding, false);
|
|
});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (type == MovementGeneratorType.Point)
|
|
{
|
|
if (pointId == PointIds.PhaseTwoFly)
|
|
{
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(33), MiscConst.GroupFly, task =>
|
|
{
|
|
_scheduler.CancelGroup(MiscConst.GroupFly);
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(2), MiscConst.GroupGround, landTask =>
|
|
{
|
|
Talk(TextIds.YellLandPhase);
|
|
me.SetDisableGravity(true);
|
|
me.GetMotionMaster().MoveAlongSplineChain(PointIds.PhaseTwoEnd, SplineChainIds.PhaseTwo, false);
|
|
});
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(2), MiscConst.GroupFly, task =>
|
|
{
|
|
Talk(TextIds.EmoteBreath);
|
|
task.Schedule(TimeSpan.FromSeconds(3), MiscConst.GroupFly, somethingTask =>
|
|
{
|
|
ResetThreatList();
|
|
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
|
|
if (target)
|
|
{
|
|
me.SetFacingToObject(target);
|
|
DoCast(target, SpellIds.RainOfBones);
|
|
}
|
|
});
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(21), MiscConst.GroupFly, task =>
|
|
{
|
|
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
|
|
if (target)
|
|
DoCast(target, SpellIds.SmokingBlastT);
|
|
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(7));
|
|
});
|
|
_scheduler.Schedule(TimeSpan.FromSeconds(17), MiscConst.GroupFly, task =>
|
|
{
|
|
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
|
|
if (target)
|
|
DoCast(target, SpellIds.SmokingBlast);
|
|
task.Repeat(TimeSpan.FromMilliseconds(1400));
|
|
});
|
|
}
|
|
else if (pointId == PointIds.PhaseTwoPreFly)
|
|
{
|
|
_scheduler.Schedule(TimeSpan.FromMilliseconds(1), task =>
|
|
{
|
|
me.GetMotionMaster().MovePoint(PointIds.PhaseTwoFly, MiscConst.FlyPosition, true);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void StartPhaseFly()
|
|
{
|
|
++_flyCount;
|
|
Talk(TextIds.YellFlyPhase);
|
|
_scheduler.CancelGroup(MiscConst.GroupGround);
|
|
me.InterruptNonMeleeSpells(false);
|
|
me.HandleEmoteCommand(Emote.OneshotLiftoff);
|
|
me.SetDisableGravity(true);
|
|
me.SetReactState(ReactStates.Passive);
|
|
me.AttackStop();
|
|
|
|
if (me.GetDistance(MiscConst.FlyPositionLeft) < me.GetDistance(MiscConst.FlyPosition))
|
|
me.GetMotionMaster().MovePoint(PointIds.PhaseTwoPreFly, MiscConst.FlyPositionLeft, true);
|
|
else if (me.GetDistance(MiscConst.FlyPositionRight) < me.GetDistance(MiscConst.FlyPosition))
|
|
me.GetMotionMaster().MovePoint(PointIds.PhaseTwoPreFly, MiscConst.FlyPositionRight, true);
|
|
else
|
|
me.GetMotionMaster().MovePoint(PointIds.PhaseTwoFly, MiscConst.FlyPosition, true);
|
|
}
|
|
|
|
public override void UpdateAI(uint diff)
|
|
{
|
|
if (!UpdateVictim() && phase != NightbanePhases.Intro)
|
|
return;
|
|
|
|
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
|
|
}
|
|
}
|
|
|
|
[Script] // 37098 - Rain of Bones
|
|
class spell_rain_of_bones_AuraScript : AuraScript
|
|
{
|
|
public override bool Validate(SpellInfo spellInfo)
|
|
{
|
|
return ValidateSpellInfo(SpellIds.SummonSkeleton);
|
|
}
|
|
|
|
void OnTrigger(AuraEffect aurEff)
|
|
{
|
|
if (aurEff.GetTickNumber() % 5 == 0)
|
|
GetTarget().CastSpell(GetTarget(), SpellIds.SummonSkeleton, true);
|
|
}
|
|
|
|
public override void Register()
|
|
{
|
|
OnEffectPeriodic.Add(new EffectPeriodicHandler(OnTrigger, 1, AuraType.PeriodicTriggerSpell));
|
|
}
|
|
}
|
|
|
|
[Script]
|
|
class go_blackened_urn : GameObjectAI
|
|
{
|
|
InstanceScript instance;
|
|
|
|
public go_blackened_urn(GameObject go) : base(go)
|
|
{
|
|
instance = go.GetInstanceScript();
|
|
}
|
|
|
|
public override bool OnGossipHello(Player player)
|
|
{
|
|
if (me.HasFlag(GameObjectFlags.InUse))
|
|
return false;
|
|
|
|
if (instance.GetBossState(DataTypes.Nightbane) == EncounterState.Done || instance.GetBossState(DataTypes.Nightbane) == EncounterState.InProgress)
|
|
return false;
|
|
|
|
Creature nightbane = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.Nightbane));
|
|
if (nightbane)
|
|
{
|
|
me.SetFlag(GameObjectFlags.InUse);
|
|
nightbane.GetAI().DoAction(MiscConst.ActionSummon);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
} |