diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index bae5ea327..312374073 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -749,7 +749,7 @@ namespace Game.Entities InitSplines(rotatedPoints, timeToTarget); } - void InitSplines(List splinePoints, uint timeToTarget) + public void InitSplines(List splinePoints, uint timeToTarget) { if (splinePoints.Count < 2) return; diff --git a/Source/Scripts/Spells/Priest.cs b/Source/Scripts/Spells/Priest.cs index 00730158b..91da07a30 100644 --- a/Source/Scripts/Spells/Priest.cs +++ b/Source/Scripts/Spells/Priest.cs @@ -16,14 +16,17 @@ */ using Framework.Constants; +using Framework.Dynamic; using Game.AI; using Game.Entities; +using Game.Maps; +using Game.Movement; using Game.Scripting; using Game.Spells; using System; using System.Collections.Generic; using System.Linq; -using Game.Maps; +using System.Numerics; namespace Scripts.Spells.Priest { @@ -40,6 +43,8 @@ namespace Scripts.Spells.Priest public const uint BodyAndSoul = 64129; public const uint BodyAndSoulSpeed = 65081; public const uint DivineBlessing = 40440; + public const uint DivineStarDamage = 122128; + public const uint DivineStarHeal = 110745; public const uint DivineWrath = 40441; public const uint FlashHeal = 2061; public const uint GuardianSpiritHeal = 48153; @@ -332,6 +337,118 @@ namespace Scripts.Spells.Priest } } + [Script] // 110744 - Divine Star + class areatrigger_pri_divine_star : AreaTriggerAI + { + TaskScheduler _scheduler = new(); + Position _casterCurrentPosition = new(); + List _affectedUnits = new(); + + public areatrigger_pri_divine_star(AreaTrigger areatrigger) : base(areatrigger) { } + + public override void OnInitialize() + { + Unit caster = at.GetCaster(); + if (caster != null) + { + _casterCurrentPosition = caster.GetPosition(); + + // Note: max. distance at which the Divine Star can travel to is 24 yards. + float divineStarXOffSet = 24.0f; + + Position destPos = _casterCurrentPosition; + at.MovePositionToFirstCollision(destPos, divineStarXOffSet, 0.0f); + + PathGenerator firstPath = new(at); + firstPath.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false); + + Vector3 endPoint = firstPath.GetPath().Last(); + + // Note: it takes 1000ms to reach 24 yards, so it takes 41.67ms to run 1 yard. + at.InitSplines(firstPath.GetPath().ToList(), (uint)(at.GetDistance(endPoint.X, endPoint.Y, endPoint.Z) * 41.67f)); + } + } + + public override void OnUpdate(uint diff) + { + _scheduler.Update(diff); + } + + public override void OnUnitEnter(Unit unit) + { + Unit caster = at.GetCaster(); + if (caster != null) + { + if (!_affectedUnits.Contains(unit.GetGUID())) + { + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, SpellIds.DivineStarDamage, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress)); + else if (caster.IsValidAssistTarget(unit)) + caster.CastSpell(unit, SpellIds.DivineStarHeal, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress)); + + _affectedUnits.Add(unit.GetGUID()); + } + } + } + + public override void OnUnitExit(Unit unit) + { + // Note: this ensures any unit receives a second hit if they happen to be inside the AT when Divine Star starts its return path. + Unit caster = at.GetCaster(); + if (caster != null) + { + if (!_affectedUnits.Contains(unit.GetGUID())) + { + if (caster.IsValidAttackTarget(unit)) + caster.CastSpell(unit, SpellIds.DivineStarDamage, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress)); + else if (caster.IsValidAssistTarget(unit)) + caster.CastSpell(unit, SpellIds.DivineStarHeal, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress)); + + _affectedUnits.Add(unit.GetGUID()); + } + } + } + + public override void OnDestinationReached() + { + Unit caster = at.GetCaster(); + if (caster == null) + return; + + if (at.GetDistance(_casterCurrentPosition) > 0.05f) + { + _affectedUnits.Clear(); + + ReturnToCaster(); + } + else + at.Remove(); + } + + void ReturnToCaster() + { + _scheduler.Schedule(TimeSpan.FromMilliseconds(0), task => + { + Unit caster = at.GetCaster(); + if (caster != null) + { + _casterCurrentPosition = caster.GetPosition(); + + List returnSplinePoints = new(); + + returnSplinePoints.Add(at.GetPosition()); + returnSplinePoints.Add(at.GetPosition()); + returnSplinePoints.Add(caster.GetPosition()); + returnSplinePoints.Add(caster.GetPosition()); + + at.InitSplines(returnSplinePoints, (uint)at.GetDistance(caster) / 24 * 1000); + + task.Repeat(TimeSpan.FromMilliseconds(250)); + } + }); + } + } + [Script] // 47788 - Guardian Spirit class spell_pri_guardian_spirit : AuraScript { diff --git a/sql/updates/world/master/2022_08_02_03_world.sql b/sql/updates/world/master/2022_08_02_03_world.sql new file mode 100644 index 000000000..ec346e080 --- /dev/null +++ b/sql/updates/world/master/2022_08_02_03_world.sql @@ -0,0 +1 @@ +UPDATE `areatrigger_create_properties` SET `ScriptName`='areatrigger_pri_divine_star', `VerifiedBuild`=44325 WHERE `Id`=2148;