diff --git a/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 AutoTargetSwitcher.cs b/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 AutoTargetSwitcher.cs index 0ee7b8b1..6be3a84d 100644 --- a/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 AutoTargetSwitcher.cs +++ b/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 AutoTargetSwitcher.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Objects.Types; using ECommons; using ECommons.Configuration; @@ -20,12 +21,15 @@ public class P4_AutoTargetSwitcher : SplatoonScript private readonly List _percentages = []; private readonly Random _random = new(); private readonly List _targets = []; + + private int _akhMornCount; private IBattleChara? _currentTarget; private Timings _currentTiming = Timings.Start; private float _lastMinPercentage; + private int _mornAfahCount; public override HashSet? ValidTerritories => [1238]; - public override Metadata? Metadata => new(4, "Garume"); + public override Metadata? Metadata => new(5, "Garume"); private Config C => Controller.GetConfig(); @@ -70,6 +74,9 @@ public override void OnSettingsDraw() ImGui.SliderFloat("Acceptable Percentage", ref C.AcceptablePercentage, 0f, 100f); ImGui.SliderInt("Interval", ref C.Interval, 100, 1000); + ImGui.Checkbox("Should Disable When Low Hp", ref C.ShouldDisableWhenLowHp); + if (C.ShouldDisableWhenLowHp) ImGui.SliderFloat("Low Hp Percentage", ref C.LowHpPercentage, 0f, 100f); + ImGui.Checkbox("Timing Mode", ref C.TimingMode); if (C.TimingMode) { @@ -133,12 +140,8 @@ public override void OnActionEffectEvent(ActionEffectSet set) _mornAfahCount++; _currentTiming = _mornAfahCount == 1 ? Timings.FirstMornAfahEnd : Timings.SecondMornAfahEnd; break; - } } - - private int _akhMornCount = 0; - private int _mornAfahCount = 0; public override void OnStartingCast(uint source, uint castId) { @@ -152,7 +155,7 @@ public override void OnStartingCast(uint source, uint castId) public override void OnUpdate() { if (!IsActive) return; - if(Svc.Condition[Dalamud.Game.ClientState.Conditions.ConditionFlag.DutyRecorderPlayback]) return; + if (Svc.Condition[ConditionFlag.DutyRecorderPlayback]) return; if (EzThrottler.Throttle("AutoTargetSwitcher", C.Interval)) { var darkGirl = DarkGirl; @@ -164,6 +167,14 @@ public override void OnUpdate() return; } + if (C.ShouldDisableWhenLowHp && darkGirl != null && lightGirl != null) + if ((float)darkGirl.CurrentHp / darkGirl.MaxHp * 100f < C.LowHpPercentage || + (float)lightGirl.CurrentHp / lightGirl.MaxHp * 100f < C.LowHpPercentage) + { + Alert("Disabling due to low hp"); + return; + } + if (darkGirl == null && lightGirl != null) { Svc.Targets.SetTarget(lightGirl); @@ -236,14 +247,11 @@ private enum Timings FirstAkhMorn, FirstMornAfahEnd, SecondAkhMorn, - SecondMornAfahEnd + SecondMornAfahEnd } private class Config : IEzConfig { - public float AcceptablePercentage = 3f; - public bool DebugMode; - public readonly List DisableTimings = [ ]; @@ -252,7 +260,12 @@ private class Config : IEzConfig [ ]; + public float AcceptablePercentage = 3f; + public bool DebugMode; + public int Interval = 300; - public bool TimingMode = false; + public float LowHpPercentage = 1f; + public bool ShouldDisableWhenLowHp; + public bool TimingMode; } } \ No newline at end of file diff --git a/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 Crystallize Time.cs b/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 Crystallize Time.cs index 3636cd5b..04f64816 100644 --- a/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 Crystallize Time.cs +++ b/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P4 Crystallize Time.cs @@ -30,12 +30,6 @@ namespace SplatoonScriptsOfficial.Duties.Dawntrail.The_Futures_Rewritten; public unsafe class P4_Crystallize_Time : SplatoonScript { - public override Metadata? Metadata => new(11, "Garume, NightmareXIV"); - public override Dictionary Changelog => new() - { - [10] = "A large addition of various functions as well as changes to general mechanic flow. Please validate settings and if possible verify that the script works fine in replay.", - [11] = "Added dragon explosion anticipation for eruption", - }; public enum Direction { North = 0, @@ -70,15 +64,23 @@ public enum Direction private Direction? _lateHourglassDirection; private Direction? _secondWaveDirection; - private bool Initialized; private List ExtraRandomness = []; + private bool Initialized; + public override Metadata? Metadata => new(12, "Garume, NightmareXIV"); + + public override Dictionary Changelog => new() + { + [10] = + "A large addition of various functions as well as changes to general mechanic flow. Please validate settings and if possible verify that the script works fine in replay.", + [11] = "Added dragon explosion anticipation for eruption" + }; private IPlayerCharacter BasePlayer { get { - if(_basePlayerOverride == "") + if (_basePlayerOverride == "") return Player.Object; return Svc.Objects.OfType() .FirstOrDefault(x => x.Name.ToString().EqualsIgnoreCase(_basePlayerOverride)) ?? Player.Object; @@ -109,9 +111,9 @@ private IPlayerCharacter BasePlayer private MechanicStage GetStage() { - if(Svc.Objects.All(x => x.DataId != 17837)) return MechanicStage.Unknown; + if (Svc.Objects.All(x => x.DataId != 17837)) return MechanicStage.Unknown; var time = SpellInWaitingDebuffTime; - if(time > 0) + if (time > 0) return time switch { < 11.5f => MechanicStage.Step6_ThirdHourglass, @@ -128,12 +130,12 @@ private MechanicStage GetStage() public override void OnStartingCast(uint source, uint castId) { - if(GetStage() == MechanicStage.Unknown) return; - if(castId == 40251 && source.GetObject() is { } sourceObject) + if (GetStage() == MechanicStage.Unknown) return; + if (castId == 40251 && source.GetObject() is { } sourceObject) { var direction = GetDirection(sourceObject.Position); - if(direction == null) return; - if(_firstWaveDirection == null) + if (direction == null) return; + if (_firstWaveDirection == null) _firstWaveDirection = direction; else _secondWaveDirection = direction; @@ -142,23 +144,23 @@ public override void OnStartingCast(uint source, uint castId) public override void OnVFXSpawn(uint target, string vfxPath) { - if(GetStage() == MechanicStage.Unknown) return; - if(vfxPath == "vfx/common/eff/dk02ht_zan0m.avfx" && + if (GetStage() == MechanicStage.Unknown) return; + if (vfxPath == "vfx/common/eff/dk02ht_zan0m.avfx" && target.GetObject() is IBattleNpc piece && _baseDirection == null) { var newDirection = GetDirection(piece.Position); - if(newDirection != null) _baseDirection = newDirection; + if (newDirection != null) _baseDirection = newDirection; } } public override void OnTetherCreate(uint source, uint target, uint data2, uint data3, uint data5) { - if(GetStage() == MechanicStage.Unknown) return; - if(source.GetObject() is not IBattleChara sourceObject) return; - if(data5 == 15) + if (GetStage() == MechanicStage.Unknown) return; + if (source.GetObject() is not IBattleChara sourceObject) return; + if (data5 == 15) { - switch(data3) + switch (data3) { case 133: _lateHourglassList.Add(sourceObject); @@ -168,43 +170,43 @@ public override void OnTetherCreate(uint source, uint target, uint data2, uint d break; } - if(_lateHourglassList.Count == 2 && _earlyHourglassList.Count == 2) + if (_lateHourglassList.Count == 2 && _earlyHourglassList.Count == 2) { var newDirection = GetDirection(_lateHourglassList[0].Position); - if(newDirection != null) _lateHourglassDirection = newDirection; + if (newDirection != null) _lateHourglassDirection = newDirection; } } } private static Direction? GetDirection(Vector3? positionNullable) { - if(positionNullable == null) return null; + if (positionNullable == null) return null; var position = positionNullable.Value; var isNorth = position.Z < 95f; var isEast = position.X > 105f; var isSouth = position.Z > 105f; var isWest = position.X < 95f; - if(isNorth && isEast) return Direction.NorthEast; - if(isEast && isSouth) return Direction.SouthEast; - if(isSouth && isWest) return Direction.SouthWest; - if(isWest && isNorth) return Direction.NorthWest; - if(isNorth) return Direction.North; - if(isEast) return Direction.East; - if(isSouth) return Direction.South; - if(isWest) return Direction.West; + if (isNorth && isEast) return Direction.NorthEast; + if (isEast && isSouth) return Direction.SouthEast; + if (isSouth && isWest) return Direction.SouthWest; + if (isWest && isNorth) return Direction.NorthWest; + if (isNorth) return Direction.North; + if (isEast) return Direction.East; + if (isSouth) return Direction.South; + if (isWest) return Direction.West; return null; } public override void OnGainBuffEffect(uint sourceId, Status Status) { - if(!IsActive || Initialized || sourceId.GetObject() is not IPlayerCharacter player) return; + if (!IsActive || Initialized || sourceId.GetObject() is not IPlayerCharacter player) return; var debuffs = player.StatusList.Where(x => AllDebuffIds.Contains(x.StatusId)); _players.TryAdd(player.GameObjectId, new PlayerData { PlayerName = player.Name.ToString() }); - foreach(var debuff in debuffs) - switch(debuff.StatusId) + foreach (var debuff in debuffs) + switch (debuff.StatusId) { case (uint)Debuff.Red: _players[player.GameObjectId].Color = Debuff.Red; @@ -223,14 +225,14 @@ public override void OnGainBuffEffect(uint sourceId, Status Status) } - if(_players.All(x => x.Value.HasDebuff)) + if (_players.All(x => x.Value.HasDebuff)) { var redBlizzards = C.PriorityData .GetPlayers(x => _players.First(y => y.Value.PlayerName == x.Name).Value is - { Color: Debuff.Red, Debuff: Debuff.Blizzard } + { Color: Debuff.Red, Debuff: Debuff.Blizzard } ); - if(redBlizzards != null) + if (redBlizzards != null) { _players[redBlizzards[0].IGameObject.GameObjectId].MoveType = MoveType.RedBlizzardWest; _players[redBlizzards[1].IGameObject.GameObjectId].MoveType = MoveType.RedBlizzardEast; @@ -238,16 +240,16 @@ public override void OnGainBuffEffect(uint sourceId, Status Status) var redAeros = C.PriorityData .GetPlayers(x => _players.First(y => y.Value.PlayerName == x.Name).Value is - { Color: Debuff.Red, Debuff: Debuff.Aero } + { Color: Debuff.Red, Debuff: Debuff.Aero } ); - if(redAeros != null) + if (redAeros != null) { _players[redAeros[0].IGameObject.GameObjectId].MoveType = MoveType.RedAeroWest; _players[redAeros[1].IGameObject.GameObjectId].MoveType = MoveType.RedAeroEast; } - foreach(var otherPlayer in _players.Where(x => x.Value.MoveType == null)) + foreach (var otherPlayer in _players.Where(x => x.Value.MoveType == null)) _players[otherPlayer.Key].MoveType = otherPlayer.Value.Debuff switch { Debuff.Holy => MoveType.BlueHoly, @@ -258,11 +260,11 @@ public override void OnGainBuffEffect(uint sourceId, Status Status) }; - if(!string.IsNullOrEmpty(C.CommandWhenBlueDebuff) && + if (!string.IsNullOrEmpty(C.CommandWhenBlueDebuff) && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) { var random = 0; - if(C.ShouldUseRandomWait) + if (C.ShouldUseRandomWait) random = RandomNumberGenerator.GetInt32((int)(C.WaitRange.X * 1000), (int)(C.WaitRange.Y * 1000)); Controller.Schedule(() => { Chat.Instance.ExecuteCommand(C.CommandWhenBlueDebuff); }, random); } @@ -282,13 +284,17 @@ public override void OnReset() _players.Clear(); _earlyHourglassList.Clear(); _lateHourglassList.Clear(); - ExtraRandomness = [(float)Random.Shared.NextDouble() - 0.5f, (float)Random.Shared.NextDouble() - 0.5f, (float)Random.Shared.NextDouble() - 0.5f]; + ExtraRandomness = + [ + (float)Random.Shared.NextDouble() - 0.5f, (float)Random.Shared.NextDouble() - 0.5f, + (float)Random.Shared.NextDouble() - 0.5f, (float)Random.Shared.NextDouble() - 0.5f + ]; } private Vector2 SwapXIfNecessary(Vector2 position) { - if(_lateHourglassDirection is Direction.NorthEast or Direction.SouthWest) + if (_lateHourglassDirection is Direction.NorthEast or Direction.SouthWest) return position; var swapX = _center.X * 2 - position.X; return new Vector2(swapX, position.Y); @@ -296,14 +302,14 @@ private Vector2 SwapXIfNecessary(Vector2 position) public override void OnSetup() { - foreach(var move in Enum.GetValues()) + foreach (var move in Enum.GetValues()) Controller.RegisterElement(move.ToString(), new Element(0) { radius = 1f, thicc = 6f }); - foreach(var stack in Enum.GetValues()) + foreach (var stack in Enum.GetValues()) Controller.RegisterElement(stack + nameof(WaveStack), new Element(0) { radius = 0.5f, @@ -323,16 +329,19 @@ public override void OnSetup() Controller.RegisterElementFromCode("SplitPosition", "{\"Name\":\"\",\"Enabled\":false,\"refX\":100.0,\"refY\":100.0,\"radius\":1.0,\"Filled\":false,\"fillIntensity\":0.5,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"thicc\":4.0,\"overlayText\":\"Spread!\",\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); - Controller.RegisterElementFromCode("KBHelper", "{\"Name\":\"\",\"type\":2,\"Enabled\":false,\"radius\":0.0,\"color\":3355508503,\"fillIntensity\":0.345,\"thicc\":4.0,\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); + Controller.RegisterElementFromCode("KBHelper", + "{\"Name\":\"\",\"type\":2,\"Enabled\":false,\"radius\":0.0,\"color\":3355508503,\"fillIntensity\":0.345,\"thicc\":4.0,\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); - Controller.RegisterElementFromCode("RedDragonExplosion1", "{\"Name\":\"\",\"refX\":87.5,\"refY\":98.0,\"refZ\":1.9073486E-06,\"radius\":13.0,\"color\":3372155112,\"fillIntensity\":0.5,\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); - Controller.RegisterElementFromCode("RedDragonExplosion2", "{\"Name\":\"\",\"refX\":112.5,\"refY\":98.0,\"refZ\":1.9073486E-06,\"radius\":13.0,\"color\":3372155112,\"fillIntensity\":0.5,\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); + Controller.RegisterElementFromCode("RedDragonExplosion1", + "{\"Name\":\"\",\"refX\":87.5,\"refY\":98.0,\"refZ\":1.9073486E-06,\"radius\":13.0,\"color\":3372155112,\"fillIntensity\":0.5,\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); + Controller.RegisterElementFromCode("RedDragonExplosion2", + "{\"Name\":\"\",\"refX\":112.5,\"refY\":98.0,\"refZ\":1.9073486E-06,\"radius\":13.0,\"color\":3372155112,\"fillIntensity\":0.5,\"refActorTetherTimeMin\":0.0,\"refActorTetherTimeMax\":0.0}"); } private void Alert(string text) { var playerOrder = GetPlayerOrder(BasePlayer); - if(Controller.TryGetElementByName("Alert", out var element)) + if (Controller.TryGetElementByName("Alert", out var element)) { element.Enabled = true; element.overlayText = text; @@ -342,8 +351,8 @@ private void Alert(string text) private static int GetPlayerOrder(IGameObject c) { - for(var i = 1; i <= 8; i++) - if((nint)FakePronoun.Resolve($"<{i}>") == c.Address) + for (var i = 1; i <= 8; i++) + if ((nint)FakePronoun.Resolve($"<{i}>") == c.Address) return i; return 0; @@ -351,7 +360,7 @@ private static int GetPlayerOrder(IGameObject c) private void HideAlert() { - if(Controller.TryGetElementByName("Alert", out var element)) + if (Controller.TryGetElementByName("Alert", out var element)) element.Enabled = false; } @@ -360,13 +369,16 @@ public override void OnUpdate() { ProcessAutoCast(); - if(GetStage() == MechanicStage.Unknown) + if (GetStage() == MechanicStage.Unknown) { Controller.GetRegisteredElements().Each(x => x.Value.Enabled = false); return; } - var spr = GetStage().EqualsAny(MechanicStage.Step1_Spread, MechanicStage.Step2_FirstHourglass) && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Eruption) && SpellInWaitingDebuffTime < 25f && Svc.Objects.OfType().Any(x => x.StatusList.Count(s => s.StatusId.EqualsAny((uint)Debuff.Red, (uint)Debuff.Blizzard)) == 2); + var spr = GetStage().EqualsAny(MechanicStage.Step1_Spread, MechanicStage.Step2_FirstHourglass) && + BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Eruption) && + SpellInWaitingDebuffTime < 25f && Svc.Objects.OfType().Any(x => + x.StatusList.Count(s => s.StatusId.EqualsAny((uint)Debuff.Red, (uint)Debuff.Blizzard)) == 2); Controller.GetElementByName("RedDragonExplosion1")!.Enabled = spr; Controller.GetElementByName("RedDragonExplosion2")!.Enabled = spr; @@ -374,14 +386,19 @@ public override void OnUpdate() { var e = Controller.GetElementByName("KBHelper")!; e.Enabled = false; - if(GetStage() == MechanicStage.Step2_FirstHourglass && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) + if (GetStage() == MechanicStage.Step2_FirstHourglass && + BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) { - var wind = Svc.Objects.OfType().OrderBy(x => Vector3.Distance(x.Position, BasePlayer.Position)).Where(x => x.StatusList.Any(s => s.StatusId == (uint)Debuff.Aero)).FirstOrDefault(); - if(wind != null && Vector3.Distance(BasePlayer.Position, wind.Position) < 5f) + var wind = Svc.Objects.OfType() + .OrderBy(x => Vector3.Distance(x.Position, BasePlayer.Position)) + .Where(x => x.StatusList.Any(s => s.StatusId == (uint)Debuff.Aero)).FirstOrDefault(); + if (wind != null && Vector3.Distance(BasePlayer.Position, wind.Position) < 5f) { e.Enabled = true; e.SetRefPosition(wind.Position); - e.SetOffPosition(new(100 + (_lateHourglassDirection.EqualsAny(Direction.NorthEast, Direction.SouthWest) ? 12 : -12), 0, 85)); + e.SetOffPosition(new Vector3( + 100 + (_lateHourglassDirection.EqualsAny(Direction.NorthEast, Direction.SouthWest) ? 12 : -12), + 0, 85)); } } } @@ -389,11 +406,11 @@ public override void OnUpdate() var myMove = _players.SafeSelect(BasePlayer.GameObjectId)?.MoveType.ToString(); var forcedPosition = ResolveRedAeroMove(); forcedPosition ??= ResolveRedBlizzardMove(); - if(myMove != null) - foreach(var move in Enum.GetValues()) - if(Controller.TryGetElementByName(move.ToString(), out var element)) + if (myMove != null) + foreach (var move in Enum.GetValues()) + if (Controller.TryGetElementByName(move.ToString(), out var element)) { - if(GetStage() == MechanicStage.Step6_ThirdHourglass && + if (GetStage() == MechanicStage.Step6_ThirdHourglass && BasePlayer.StatusList.All(x => x.StatusId != (uint)Debuff.Blue)) { element.Enabled = false; @@ -403,20 +420,20 @@ public override void OnUpdate() element.Enabled = C.ShowOther; element.color = EColor.Red.ToUint(); - if(myMove == move.ToString()) + if (myMove == move.ToString()) { element.Enabled = true; element.color = GradientColor.Get(C.BaitColor1, C.BaitColor2).ToUint(); element.tether = true; - if(forcedPosition == null) continue; + if (forcedPosition == null) continue; element.SetOffPosition(forcedPosition.Value.ToVector3(0)); element.radius = 0.4f; } } - if(forcedPosition != null) return; - switch(GetStage()) + if (forcedPosition != null) return; + switch (GetStage()) { case MechanicStage.Step1_Spread: BurnHourglassUniversal(); @@ -428,19 +445,19 @@ public override void OnUpdate() BurnHourglassUniversal(); break; case MechanicStage.Step4_SecondHourglass: - if(C.HitTiming == HitTiming.Early && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) + if (C.HitTiming == HitTiming.Early && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) HitDragonAndAero(); else BurnHourglassUniversal(); break; case MechanicStage.Step5_PerformDodges: - if(C.HitTiming == HitTiming.Late && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) + if (C.HitTiming == HitTiming.Late && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) HitDragonAndAero(); else BurnHourglassUniversal(); break; case MechanicStage.Step6_ThirdHourglass: - if(BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) + if (BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) CorrectCleanse(); else PlaceReturn(); @@ -453,60 +470,58 @@ public override void OnUpdate() private void BurnHourglassUniversal() { - if(GetStage() < MechanicStage.Step2_FirstHourglass) BurnYellowHourglass(); - else if(GetStage() < MechanicStage.Step4_SecondHourglass) BurnHourglass(); - else if(GetStage() < MechanicStage.Step6_ThirdHourglass) BurnPurpleHourglass(); + if (GetStage() < MechanicStage.Step2_FirstHourglass) BurnYellowHourglass(); + else if (GetStage() < MechanicStage.Step4_SecondHourglass) BurnHourglass(); + else if (GetStage() < MechanicStage.Step6_ThirdHourglass) BurnPurpleHourglass(); + } + + private void AutoCast(uint actionId) + { + if (!Svc.Condition[ConditionFlag.DutyRecorderPlayback]) + { + if (ActionManager.Instance()->GetActionStatus(ActionType.Action, actionId) == 0 && + EzThrottler.Throttle(InternalData.FullName + "AutoCast", 100)) + Chat.Instance.ExecuteAction(actionId); + } + else + { + if (EzThrottler.Throttle(InternalData.FullName + "InformCast", 100)) + DuoLog.Information( + $"Would use mitigation action {ExcelActionHelper.GetActionName(actionId)} if possible"); + } } private void ProcessAutoCast() { try { - if(Svc.Objects.Any(x => x.DataId == 17837) && !BasePlayer.IsDead) + if (Svc.Objects.Any(x => x.DataId == 17837) && !BasePlayer.IsDead) { - if(C.UseKbiAuto && - BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Return && x.RemainingTime < 2f + ExtraRandomness.SafeSelect(0))) + if (C.UseKbiAuto && + BasePlayer.StatusList.Any(x => + x.StatusId == (uint)Debuff.Return && x.RemainingTime < 2f + ExtraRandomness.SafeSelect(0))) //7559 : surecast //7548 : arm's length UseAntiKb(); - if(C.UseMitigation && C.MitigationAction != 0 && - BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Return && x.RemainingTime < 6f + ExtraRandomness.SafeSelect(1))) - { - if(!Svc.Condition[ConditionFlag.DutyRecorderPlayback]) - { - if(ActionManager.Instance()->GetActionStatus(ActionType.Action, C.MitigationAction) == 0 && - EzThrottler.Throttle(InternalData.FullName + "AutoCast", 100)) - Chat.Instance.ExecuteAction(C.MitigationAction); - } - else - { - if(EzThrottler.Throttle(InternalData.FullName + "InformCast", 100)) - DuoLog.Information( - $"Would use mitigation action {ExcelActionHelper.GetActionName(C.MitigationAction)} if possible"); - } - } + if (C.UseMitigation && C.MitigationAction != 0 && + BasePlayer.StatusList.Any(x => + x.StatusId == (uint)Debuff.Return && x.RemainingTime < 6f + ExtraRandomness.SafeSelect(1))) + AutoCast(C.MitigationAction); - if(C is { UseSprintAuto: true, ShouldGoNorthRedBlizzard: true } && + if (C.UseTankMitigation && C.TankMitigationAction != 0 && + BasePlayer.StatusList.Any(x => + x.StatusId == (uint)Debuff.Return && x.RemainingTime < 6f + ExtraRandomness.SafeSelect(1))) + AutoCast(C.TankMitigationAction); + + if (C is { UseSprintAuto: true, ShouldGoNorthRedBlizzard: true } && BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red) && - BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blizzard && x.RemainingTime < 1f + ExtraRandomness.SafeSelect(2))) - { - if(!Svc.Condition[ConditionFlag.DutyRecorderPlayback]) - { - if(ActionManager.Instance()->GetActionStatus(ActionType.Action, 29057) == 0 && - EzThrottler.Throttle(InternalData.FullName + "AutoCast", 100)) - Chat.Instance.ExecuteAction(29057); - } - else - { - if(EzThrottler.Throttle(InternalData.FullName + "InformCast", 100)) - DuoLog.Information( - $"Would use sprint action {ExcelActionHelper.GetActionName(29057)} if possible"); - } - } + BasePlayer.StatusList.Any(x => + x.StatusId == (uint)Debuff.Blizzard && x.RemainingTime < 1f + ExtraRandomness.SafeSelect(3))) + AutoCast(29057); } } - catch(Exception e) + catch (Exception e) { e.Log(); } @@ -514,15 +529,15 @@ private void ProcessAutoCast() private void UseAntiKb() { - foreach(var x in (uint[])[7559, 7548]) - if(!Svc.Condition[ConditionFlag.DutyRecorderPlayback]) + foreach (var x in (uint[]) [7559, 7548]) + if (!Svc.Condition[ConditionFlag.DutyRecorderPlayback]) { - if(ActionManager.Instance()->GetActionStatus(ActionType.Action, x) == 0 && + if (ActionManager.Instance()->GetActionStatus(ActionType.Action, x) == 0 && EzThrottler.Throttle(InternalData.FullName + "AutoCast", 100)) Chat.Instance.ExecuteAction(x); } else { - if(EzThrottler.Throttle(InternalData.FullName + "InformCast", 100)) + if (EzThrottler.Throttle(InternalData.FullName + "InformCast", 100)) DuoLog.Information( $"Would use kb immunity action {ExcelActionHelper.GetActionName(x)} if possible"); } @@ -530,7 +545,7 @@ private void UseAntiKb() private void BurnYellowHourglass() { - foreach(var player in Enum.GetValues()) + foreach (var player in Enum.GetValues()) { var position = player switch { @@ -546,7 +561,7 @@ private void BurnYellowHourglass() }; position = SwapXIfNecessary(position); - if(Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) + if (Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) { element.radius = 0.5f; element.SetOffPosition(position.ToVector3(0)); @@ -556,7 +571,7 @@ private void BurnYellowHourglass() private void IceHitDragon() { - foreach(var player in Enum.GetValues()) + foreach (var player in Enum.GetValues()) { var position = player switch { @@ -572,7 +587,7 @@ private void IceHitDragon() }; position = SwapXIfNecessary(position); - if(Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) + if (Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) { element.radius = 0.5f; element.SetOffPosition(position.ToVector3(0)); @@ -580,7 +595,7 @@ private void IceHitDragon() } var myMove = _players.SafeSelect(BasePlayer.GameObjectId)?.MoveType; - if(myMove is MoveType.RedBlizzardEast or MoveType.RedBlizzardWest) + if (myMove is MoveType.RedBlizzardEast or MoveType.RedBlizzardWest) { var remainingTime = BasePlayer.StatusList.FirstOrDefault(x => x.StatusId == (uint)Debuff.Blizzard) ?.RemainingTime; @@ -590,7 +605,7 @@ private void IceHitDragon() private void BurnHourglass() { - foreach(var player in Enum.GetValues()) + foreach (var player in Enum.GetValues()) { var position = player switch { @@ -606,7 +621,7 @@ private void BurnHourglass() }; position = SwapXIfNecessary(position); - if(Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) + if (Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) { element.radius = 1f; element.SetOffPosition(position.ToVector3(0)); @@ -616,7 +631,7 @@ private void BurnHourglass() private void BurnPurpleHourglass() { - foreach(var player in Enum.GetValues()) + foreach (var player in Enum.GetValues()) { var position = player switch { @@ -632,7 +647,7 @@ private void BurnPurpleHourglass() }; position = SwapXIfNecessary(position); - if(Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) + if (Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) { element.radius = 1f; element.SetOffPosition(position.ToVector3(0)); @@ -644,7 +659,7 @@ private void BurnPurpleHourglass() private void HitDragonAndAero() { - foreach(var player in Enum.GetValues()) + foreach (var player in Enum.GetValues()) { Direction? returnDirection = (_firstWaveDirection, _secondWaveDirection) switch { @@ -681,10 +696,10 @@ private void HitDragonAndAero() _ => null }; - if(position != null) + if (position != null) { position = SwapXIfNecessary(position.Value); - if(Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) + if (Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) { element.radius = 2f; element.SetOffPosition(position.Value.ToVector3(0)); @@ -693,13 +708,13 @@ private void HitDragonAndAero() } var myMove = _players.SafeSelect(BasePlayer.GameObjectId)?.MoveType; - if(myMove is MoveType.RedAeroEast or MoveType.RedAeroWest) + if (myMove is MoveType.RedAeroEast or MoveType.RedAeroWest) Alert(C.HitDragonText.Get()); } private string SwapIfNecessary(MoveType move) { - if(_lateHourglassDirection is Direction.NorthEast or Direction.SouthWest) + if (_lateHourglassDirection is Direction.NorthEast or Direction.SouthWest) return move.ToString(); return move switch { @@ -713,12 +728,12 @@ private string SwapIfNecessary(MoveType move) private void CorrectCleanse() { - foreach(var player in Enum.GetValues()) + foreach (var player in Enum.GetValues()) { var direction = Direction.West; - if(C.PrioritizeMarker && + if (C.PrioritizeMarker && _players.FirstOrDefault(x => x.Value.PlayerName == BasePlayer.Name.ToString()).Value?.Marker is - { } marker) + { } marker) { direction = marker switch { @@ -731,13 +746,13 @@ private void CorrectCleanse() } else { - if(player == C.WestSentence) + if (player == C.WestSentence) direction = Direction.West; - else if(player == C.SouthWestSentence) + else if (player == C.SouthWestSentence) direction = Direction.SouthWest; - else if(player == C.SouthEastSentence) + else if (player == C.SouthEastSentence) direction = Direction.SouthEast; - else if(player == C.EastSentence) + else if (player == C.EastSentence) direction = Direction.East; } @@ -752,14 +767,14 @@ private void CorrectCleanse() _ => new Vector2(100, 100) }; - if(Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) + if (Controller.TryGetElementByName(SwapIfNecessary(player), out var element)) { element.radius = 2f; element.SetOffPosition(position.ToVector3(0)); } } - if(BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) + if (BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Blue)) Alert(C.CleanseText.Get()); else HideAlert(); @@ -767,9 +782,9 @@ private void CorrectCleanse() private void PlaceReturn() { - if(C.NukemaruRewind) + if (C.NukemaruRewind) NukemaruPlaceReturn(); - else if(C.KBIRewind) + else if (C.KBIRewind) KBIPlaceReturn(); else DefaultPlaceReturn(); @@ -791,7 +806,7 @@ private void KBIPlaceReturn() (Direction.East, Direction.North) => Direction.North, _ => throw new InvalidOperationException() }; - if(Controller.TryGetElementByName(WaveStack.West + nameof(WaveStack), out var myElement)) + if (Controller.TryGetElementByName(WaveStack.West + nameof(WaveStack), out var myElement)) { myElement.Enabled = true; myElement.tether = true; @@ -838,7 +853,7 @@ private void NukemaruPlaceReturn() MathHelper.RotateWorldPoint(Vector3.Zero, ((int)direction).DegreesToRadians(), -Vector3.UnitZ * 3f); - if(Controller.TryGetElementByName(WaveStack.West + nameof(WaveStack), out var myElement)) + if (Controller.TryGetElementByName(WaveStack.West + nameof(WaveStack), out var myElement)) { myElement.Enabled = true; myElement.tether = true; @@ -894,7 +909,7 @@ private void DefaultPlaceReturn() var westPosition = basePosition; var eastPosition = basePosition; - switch(returnDirection) + switch (returnDirection) { case Direction.NorthEast: westTankPosition += new Vector2(-3f, -0.5f); @@ -922,8 +937,8 @@ private void DefaultPlaceReturn() break; } - foreach(var stack in Enum.GetValues()) - if(Controller.TryGetElementByName(stack + nameof(WaveStack), out var element)) + foreach (var stack in Enum.GetValues()) + if (Controller.TryGetElementByName(stack + nameof(WaveStack), out var element)) { element.Enabled = C.ShowOther; element.radius = stack is WaveStack.WestTank or WaveStack.EastTank ? 0.5f : 1.2f; @@ -937,7 +952,7 @@ private void DefaultPlaceReturn() }); } - if(Controller.TryGetElementByName(myStack + nameof(WaveStack), out var myElement)) + if (Controller.TryGetElementByName(myStack + nameof(WaveStack), out var myElement)) { myElement.Enabled = true; myElement.tether = true; @@ -948,7 +963,7 @@ private void DefaultPlaceReturn() private void Split() { Controller.GetRegisteredElements().Each(x => x.Value.Enabled = false); - if(C.HighlightSplitPosition && Controller.TryGetElementByName("SplitPosition", out var myElement)) + if (C.HighlightSplitPosition && Controller.TryGetElementByName("SplitPosition", out var myElement)) { myElement.Enabled = true; myElement.tether = true; @@ -965,7 +980,7 @@ This script has not been thoroughly tested. It may not work properly. If you encounter any bugs, please let us know. """); - if(ImGuiEx.CollapsingHeader("General")) + if (ImGuiEx.CollapsingHeader("General")) { ImGuiEx.Text("Priority"); ImGui.Indent(); @@ -979,7 +994,7 @@ It may not work properly. ImGui.Checkbox("Should Go North When Red Blizzard Hit to Dragon", ref C.ShouldGoNorthRedBlizzard); ImGuiEx.HelpMarker( "During Red Blizzard, if there is no one in the north, the navigation will appear in the north instead of the south."); - if(C.ShouldGoNorthRedBlizzard) + if (C.ShouldGoNorthRedBlizzard) { ImGui.Indent(); ImGui.Checkbox("Automatically use sprint action ~1 seconds", ref C.UseSprintAuto); @@ -990,24 +1005,24 @@ It may not work properly. ImGuiEx.Text("Sentence Moves"); ImGui.Indent(); ImGui.Checkbox("PrioritizeMarker", ref C.PrioritizeMarker); - if(C.PrioritizeMarker) + if (C.PrioritizeMarker) { ImGui.Indent(); ImGui.InputText("Execute Command When Blue Debuff Gained", ref C.CommandWhenBlueDebuff, 30); ImGui.Checkbox("Random Wait", ref C.ShouldUseRandomWait); - if(C.ShouldUseRandomWait) + if (C.ShouldUseRandomWait) { var minWait = C.WaitRange.X; var maxWait = C.WaitRange.Y; ImGui.SliderFloat2("Wait Range (sec)", ref C.WaitRange, 0f, 3f, "%.1f"); - if(Math.Abs(minWait - C.WaitRange.X) > 0.01f) + if (Math.Abs(minWait - C.WaitRange.X) > 0.01f) { - if(C.WaitRange.X > C.WaitRange.Y) + if (C.WaitRange.X > C.WaitRange.Y) C.WaitRange.Y = C.WaitRange.X; } - else if(Math.Abs(maxWait - C.WaitRange.Y) > 0.01f) + else if (Math.Abs(maxWait - C.WaitRange.Y) > 0.01f) { - if(C.WaitRange.Y < C.WaitRange.X) + if (C.WaitRange.Y < C.WaitRange.X) C.WaitRange.X = C.WaitRange.Y; } } @@ -1031,14 +1046,14 @@ It may not work properly. ImGuiEx.TextWrapped(EColor.RedBright, "You must go to Registered Elements section and put \"SplitPosition\" element to where you want it to be. Go to Eden's Promise: Eternity undersized for a preview, if necessary."); - if(C.HighlightSplitPosition) - if(Controller.TryGetElementByName("SplitPosition", out var element)) + if (C.HighlightSplitPosition) + if (Controller.TryGetElementByName("SplitPosition", out var element)) { ImGui.Indent(); ImGui.Text($"Position:{element.refX}, {element.refY}"); ImGuiEx.EnumCombo("Edit Direction", ref _editSplitElementDirection); ImGui.InputFloat("Edit Radius", ref _editSplitElementRadius, 0.1f); - if(ImGui.Button("Set")) + if (ImGui.Button("Set")) { var position = new Vector3(100, 0, 100) + MathHelper.RotateWorldPoint(Vector3.Zero, ((int)_editSplitElementDirection).DegreesToRadians(), @@ -1059,14 +1074,14 @@ It may not work properly. ImGui.Checkbox("Knockback immunity return positions (beta)", ref kbiRewind); ImGui.Checkbox("Nukemaru's return positions", ref nukemaruRewind); - if(!C.KBIRewind && kbiRewind) + if (!C.KBIRewind && kbiRewind) nukemaruRewind = false; - else if(!C.NukemaruRewind && nukemaruRewind) kbiRewind = false; + else if (!C.NukemaruRewind && nukemaruRewind) kbiRewind = false; C.KBIRewind = kbiRewind; C.NukemaruRewind = nukemaruRewind; - if(C.NukemaruRewind) + if (C.NukemaruRewind) { ImGui.Indent(); ImGuiEx.EnumCombo("When North East Wave", ref C.NukemaruRewindPositionWhenNorthEastWave); @@ -1076,7 +1091,7 @@ It may not work properly. ImGui.Unindent(); } - if(C is { KBIRewind: false, NukemaruRewind: false }) + if (C is { KBIRewind: false, NukemaruRewind: false }) { ImGui.Checkbox("Is Tank", ref C.IsTank); @@ -1144,7 +1159,7 @@ It may not work properly. ImGui.Separator(); ImGui.Checkbox("Automatically use KB immunity action ~2 seconds before rewind", ref C.UseKbiAuto); ImGui.Checkbox("Automatically use mitigation action ~4 seconds before rewind", ref C.UseMitigation); - if(C.UseMitigation) + if (C.UseMitigation) { ImGui.Indent(); var actions = Ref>.Get(InternalData.FullName + "mitigations", @@ -1155,35 +1170,51 @@ It may not work properly. ImGui.Unindent(); } + ImGui.Checkbox("Automatically use tank mitigation action ~4 seconds before rewind", + ref C.UseTankMitigation); + if (C.UseTankMitigation) + { + ImGui.Indent(); + var actions = Ref>.Get(InternalData.FullName + "tankMitigations", + () => Svc.Data.GetExcelSheet() + .Where(x => x.IsPlayerAction && + (x.ClassJobCategory.Value.DRK || x.ClassJobCategory.Value.WAR || + x.ClassJobCategory.Value.PLD || x.ClassJobCategory.Value.GNB) && + x.ActionCategory.RowId == 4) + .ToDictionary(x => x.RowId, x => x.Name.ExtractText())); + ImGuiEx.Combo("Select tank action", ref C.TankMitigationAction, actions.Keys, names: actions); + ImGui.Unindent(); + } + ImGui.Separator(); ImGui.Checkbox("Show Other", ref C.ShowOther); - if(ImGui.CollapsingHeader("Prio list")) + if (ImGui.CollapsingHeader("Prio list")) { ImGuiEx.Text(C.PriorityData.GetPlayers(x => true).Select(x => x.NameWithWorld).Print("\n")); ImGui.Separator(); ImGuiEx.Text("Red bliz:"); ImGuiEx.Text(C.PriorityData.GetPlayers(x => _players.First(y => y.Value.PlayerName == x.Name).Value is - { Color: Debuff.Red, Debuff: Debuff.Blizzard }).Select(x => x.NameWithWorld).Print("\n")); + { Color: Debuff.Red, Debuff: Debuff.Blizzard }).Select(x => x.NameWithWorld).Print("\n")); ImGui.Separator(); ImGuiEx.Text("Red aero:"); ImGuiEx.Text(C.PriorityData.GetPlayers(x => _players.First(y => y.Value.PlayerName == x.Name).Value is - { Color: Debuff.Red, Debuff: Debuff.Aero }).Select(x => x.NameWithWorld).Print("\n")); + { Color: Debuff.Red, Debuff: Debuff.Aero }).Select(x => x.NameWithWorld).Print("\n")); } } - if(ImGuiEx.CollapsingHeader("Debug")) + if (ImGuiEx.CollapsingHeader("Debug")) { ImGuiEx.Text($"Stage: {GetStage()}, remaining time = {SpellInWaitingDebuffTime}"); ImGui.SetNextItemWidth(200); ImGui.InputText("Player override", ref _basePlayerOverride, 50); ImGui.SameLine(); ImGui.SetNextItemWidth(200); - if(ImGui.BeginCombo("Select..", "Select...")) + if (ImGui.BeginCombo("Select..", "Select...")) { - foreach(var x in Svc.Objects.OfType()) - if(ImGui.Selectable(x.GetNameWithWorld())) + foreach (var x in Svc.Objects.OfType()) + if (ImGui.Selectable(x.GetNameWithWorld())) _basePlayerOverride = x.Name.ToString(); ImGui.EndCombo(); } @@ -1204,7 +1235,7 @@ It may not work properly. ImGuiEx.EnumCombo("First Wave Direction", ref _debugDirection1); ImGuiEx.EnumCombo("Second Wave Direction", ref _debugDirection2); - if(ImGui.Button("Show Return Placement")) + if (ImGui.Button("Show Return Placement")) { _firstWaveDirection = _debugDirection1; _secondWaveDirection = _debugDirection2; @@ -1216,8 +1247,8 @@ public override void OnActorControl(uint sourceId, uint command, uint p1, uint p uint p6, ulong targetId, byte replaying) { - if(GetStage() == MechanicStage.Unknown) return; - if(command == 502) + if (GetStage() == MechanicStage.Unknown) return; + if (command == 502) try { _players[p2].Marker = (MarkerType)p1; @@ -1230,48 +1261,48 @@ public override void OnActorControl(uint sourceId, uint command, uint p1, uint p private Vector2? ResolveRedAeroMove() { - if(_players.SafeSelect(BasePlayer.GameObjectId)?.MoveType? - .EqualsAny(MoveType.RedAeroEast, MoveType.RedAeroWest) != true) return null; + if (_players.SafeSelect(BasePlayer.GameObjectId)?.MoveType? + .EqualsAny(MoveType.RedAeroEast, MoveType.RedAeroWest) != true) return null; var isPlayerWest = _players.SafeSelect(BasePlayer.GameObjectId)?.MoveType == MoveType.RedAeroWest; var isLateHourglassSameSide = _lateHourglassDirection is Direction.NorthEast or Direction.SouthWest == isPlayerWest; var stage = GetStage(); - switch(stage) + switch (stage) { case MechanicStage.Step1_Spread: return MirrorX(RedAeroEastMovements.Step1_InitialDodge, isPlayerWest); case MechanicStage.Step2_FirstHourglass when isLateHourglassSameSide: - { - if(BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Aero)) - return MirrorX(RedAeroEastMovements.Step2_KnockPlayers, isPlayerWest); + { + if (BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Aero)) + return MirrorX(RedAeroEastMovements.Step2_KnockPlayers, isPlayerWest); - Alert(C.HitDragonText.Get()); - return (isPlayerWest ? WestDragon : EastDragon)?.Position.ToVector2(); - } + Alert(C.HitDragonText.Get()); + return (isPlayerWest ? WestDragon : EastDragon)?.Position.ToVector2(); + } case MechanicStage.Step2_FirstHourglass: return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); case MechanicStage.Step3_IcesAndWinds when isLateHourglassSameSide: + { + if (BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) { - if(BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) - { - Alert(C.HitDragonText.Get()); - return (isPlayerWest ? WestDragon : EastDragon)?.Position.ToVector2(); - } - - return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); + Alert(C.HitDragonText.Get()); + return (isPlayerWest ? WestDragon : EastDragon)?.Position.ToVector2(); } + + return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); + } case MechanicStage.Step3_IcesAndWinds: return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); case MechanicStage.Step4_SecondHourglass when isLateHourglassSameSide: + { + if (BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) { - if(BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) - { - Alert(C.HitDragonText.Get()); - return (isPlayerWest ? WestDragon : EastDragon)?.Position.ToVector2(); - } - - return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); + Alert(C.HitDragonText.Get()); + return (isPlayerWest ? WestDragon : EastDragon)?.Position.ToVector2(); } + + return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); + } case MechanicStage.Step4_SecondHourglass: return MirrorX(RedAeroEastMovements.Step3_DodgeSecondHourglass, isPlayerWest); case MechanicStage.Step5_PerformDodges when BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red): @@ -1286,19 +1317,19 @@ public override void OnActorControl(uint sourceId, uint command, uint p1, uint p private Vector2? ResolveRedBlizzardMove() { - if(_players.SafeSelect(BasePlayer.GameObjectId)?.MoveType?.EqualsAny(MoveType.RedBlizzardWest, + if (_players.SafeSelect(BasePlayer.GameObjectId)?.MoveType?.EqualsAny(MoveType.RedBlizzardWest, MoveType.RedBlizzardEast) != true) return null; var isPlayerWest = _players.SafeSelect(BasePlayer.GameObjectId)?.MoveType == MoveType.RedBlizzardWest; var isLateHourglassSameSide = (_lateHourglassDirection == Direction.NorthEast || _lateHourglassDirection == Direction.SouthWest) == isPlayerWest; var stage = GetStage(); - if(stage <= MechanicStage.Step5_PerformDodges) + if (stage <= MechanicStage.Step5_PerformDodges) { - if(BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) return null; - if(isLateHourglassSameSide) + if (BasePlayer.StatusList.Any(x => x.StatusId == (uint)Debuff.Red)) return null; + if (isLateHourglassSameSide) { - if(stage <= MechanicStage.Step4_SecondHourglass && !C.ShouldGoNorthRedBlizzard) + if (stage <= MechanicStage.Step4_SecondHourglass && !C.ShouldGoNorthRedBlizzard) return MirrorX(new Vector2(119, 103), isPlayerWest); return MirrorX(new Vector2(105, 82), isPlayerWest); } @@ -1311,7 +1342,7 @@ public override void OnActorControl(uint sourceId, uint command, uint p1, uint p private static Vector2 MirrorX(Vector2 x, bool mirror) { - if(mirror) + if (mirror) return x with { X = 100f - Math.Abs(x.X - 100f) }; return x; } @@ -1476,9 +1507,11 @@ private class Config : IEzConfig public MoveType SouthEastSentence = MoveType.BlueHoly; public MoveType SouthWestSentence = MoveType.BlueWater; public InternationalString SplitText = new() { En = "Split", Jp = "散開!" }; + public uint TankMitigationAction; public bool UseKbiAuto; public bool UseMitigation; public bool UseSprintAuto; + public bool UseTankMitigation; public Vector2 WaitRange = new(0.5f, 1.5f); public MoveType WestSentence = MoveType.BlueEruption; public Direction WhenAttack1 = Direction.East; diff --git a/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P5 Paradise Regained.cs b/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P5 Paradise Regained.cs index 26cd1cde..16515a43 100644 --- a/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P5 Paradise Regained.cs +++ b/SplatoonScripts/Duties/Dawntrail/The Futures Rewritten/P5 Paradise Regained.cs @@ -88,7 +88,7 @@ public enum TowerType private State _state = State.None; public override HashSet? ValidTerritories => [1238]; - public override Metadata? Metadata => new(3, "Garume"); + public override Metadata? Metadata => new(4, "Garume"); public Config C => Controller.GetConfig(); @@ -575,6 +575,13 @@ public void Reset() _firstAttack = null; _towers.Clear(); } + + private readonly Dictionary _towerPositions = new() + { + {Direction.NorthWest, new Vector2(93.93782f, 96.5f)}, + {Direction.NorthEast, new Vector2(106.0622f, 96.5f)}, + {Direction.South, new Vector2(100f, 107f)} + }; public override void OnMapEffect(uint position, ushort data1, ushort data2) { @@ -606,10 +613,10 @@ public override void OnMapEffect(uint position, ushort data1, ushort data2) { var diff = _towers[0].AngleDifference(_towers[1]); _towers[1].IsLeft = diff <= 180; - break; - } - case 3: - { + + var lastTowerPosition = _towerPositions.First(x => x.Key != _towers[0].Direction && x.Key != _towers[1].Direction); + _towers.Add(new TowerData {Position = lastTowerPosition.Value, Direction = lastTowerPosition.Key}); + _towers[2].IsLeft = !_towers[1].IsLeft; break; }