diff --git a/BossMod/ActionQueue/ActionDefinition.cs b/BossMod/ActionQueue/ActionDefinition.cs index 4a84eaecfe..d512e34c70 100644 --- a/BossMod/ActionQueue/ActionDefinition.cs +++ b/BossMod/ActionQueue/ActionDefinition.cs @@ -261,6 +261,20 @@ public void Dispose() public static Actor? FindEsunaTarget(WorldState ws) => ws.Party.WithoutSlot().FirstOrDefault(p => p.Statuses.Any(s => Utils.StatusIsRemovable(s.ID))); public static Actor? SmartTargetEsunable(WorldState ws, Actor player, Actor? primaryTarget, AIHints hints) => SmartTargetFriendly(primaryTarget) ?? FindEsunaTarget(ws) ?? player; + // check if dashing to target will put the player inside a forbidden zone + // TODO should we check if dash trajectory will cross any zones with imminent activation? + public static bool PreventDashIfDangerous(WorldState _, Actor player, Actor? target, AIHints hints) + { + if (target == null || !Service.Config.Get().PreventDangerousDash) + return false; + + var dist = player.DistanceToHitbox(target); + var dir = player.DirectionTo(target).Normalized(); + var src = player.Position; + var proj = dist > 0 ? src + dir * MathF.Max(0, dist) : src; + return hints.ForbiddenZones.Any(d => d.shapeDistance(proj) < 0); + } + public BitMask SpellAllowedClasses(Lumina.Excel.Sheets.Action data) { BitMask res = default; diff --git a/BossMod/ActionQueue/Casters/RDM.cs b/BossMod/ActionQueue/Casters/RDM.cs index ea47fbee68..3b87706407 100644 --- a/BossMod/ActionQueue/Casters/RDM.cs +++ b/BossMod/ActionQueue/Casters/RDM.cs @@ -162,5 +162,7 @@ private void Customize(ActionDefinitions d) { d.RegisterChargeIncreaseTrait(AID.Acceleration, TraitID.EnhancedAcceleration); // *** add any properties that can't be autogenerated here *** + + d.Spell(AID.CorpsACorps)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionQueue/Casters/SMN.cs b/BossMod/ActionQueue/Casters/SMN.cs index a58d4afc4e..9a50bef5d4 100644 --- a/BossMod/ActionQueue/Casters/SMN.cs +++ b/BossMod/ActionQueue/Casters/SMN.cs @@ -230,5 +230,7 @@ private void Customize(ActionDefinitions d) { d.RegisterChargeIncreaseTrait(AID.RadiantAegis, TraitID.EnhancedRadiantAegis); // *** add any properties that can't be autogenerated here *** + + d.Spell(AID.CrimsonCyclone)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionQueue/Melee/DRG.cs b/BossMod/ActionQueue/Melee/DRG.cs index 9d857284d7..7785531625 100644 --- a/BossMod/ActionQueue/Melee/DRG.cs +++ b/BossMod/ActionQueue/Melee/DRG.cs @@ -166,5 +166,7 @@ private void Customize(ActionDefinitions d) //d.Spell(AID.TrueThrust)!.TransformAction = d.Spell(AID.RaidenThrust)!.TransformAction = () => ActionID.MakeSpell(_state.BestTrueThrust); //d.Spell(AID.DoomSpike)!.TransformAction = d.Spell(AID.DraconianFury)!.TransformAction = () => ActionID.MakeSpell(_state.BestDoomSpike); //d.Spell(AID.Geirskogul)!.TransformAction = d.Spell(AID.Nastrond)!.TransformAction = () => ActionID.MakeSpell(_state.BestGeirskogul); + + d.Spell(AID.Stardiver)!.ForbidExecute = d.Spell(AID.DragonfireDive)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionQueue/Melee/NIN.cs b/BossMod/ActionQueue/Melee/NIN.cs index 07927bf6f4..50599bb802 100644 --- a/BossMod/ActionQueue/Melee/NIN.cs +++ b/BossMod/ActionQueue/Melee/NIN.cs @@ -194,6 +194,8 @@ public void Dispose() { } private void Customize(ActionDefinitions d) { d.RegisterChargeIncreaseTrait(AID.Shukuchi, TraitID.EnhancedShukuchiII); + + d.Spell(AID.ForkedRaiju)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionQueue/Melee/SAM.cs b/BossMod/ActionQueue/Melee/SAM.cs index 3f641f0c76..f74232a412 100644 --- a/BossMod/ActionQueue/Melee/SAM.cs +++ b/BossMod/ActionQueue/Melee/SAM.cs @@ -161,5 +161,7 @@ private void Customize(ActionDefinitions d) // upgrades (TODO: don't think we actually care...) //d.Spell(AID.Iaijutsu)!.TransformAction = () => ActionID.MakeSpell(_state.BestIai); //d.Spell(AID.MeikyoShisui)!.Condition = _ => _state.MeikyoLeft == 0; + + d.Spell(AID.HissatsuGyoten)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionQueue/Tanks/PLD.cs b/BossMod/ActionQueue/Tanks/PLD.cs index 287fee4029..fc4dadabb2 100644 --- a/BossMod/ActionQueue/Tanks/PLD.cs +++ b/BossMod/ActionQueue/Tanks/PLD.cs @@ -170,5 +170,7 @@ private void Customize(ActionDefinitions d) //d.Spell(AID.HallowedGround)!.EffectDuration = 10; //d.Spell(AID.DivineVeil)!.EffectDuration = 30; // TODO: Intervention effect duration? + + d.Spell(AID.Intervene)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionQueue/Tanks/WAR.cs b/BossMod/ActionQueue/Tanks/WAR.cs index 2b453486dd..564def1682 100644 --- a/BossMod/ActionQueue/Tanks/WAR.cs +++ b/BossMod/ActionQueue/Tanks/WAR.cs @@ -189,5 +189,7 @@ private void Customize(ActionDefinitions d) //d.Spell(AID.StormEye)!.TransformAction = config.STCombos ? () => ActionID.MakeSpell(Rotation.GetNextSTComboAction(ComboLastMove, AID.StormEye)) : null; //d.Spell(AID.StormPath)!.TransformAction = config.STCombos ? () => ActionID.MakeSpell(Rotation.GetNextSTComboAction(ComboLastMove, AID.StormPath)) : null; //d.Spell(AID.MythrilTempest)!.TransformAction = config.AOECombos ? () => ActionID.MakeSpell(Rotation.GetNextAOEComboAction(ComboLastMove)) : null; + + d.Spell(AID.Onslaught)!.ForbidExecute = d.Spell(AID.PrimalRend)!.ForbidExecute = ActionDefinitions.PreventDashIfDangerous; } } diff --git a/BossMod/ActionTweaks/ActionTweaksConfig.cs b/BossMod/ActionTweaks/ActionTweaksConfig.cs index 12f4b13d15..5b38395729 100644 --- a/BossMod/ActionTweaks/ActionTweaksConfig.cs +++ b/BossMod/ActionTweaks/ActionTweaksConfig.cs @@ -76,4 +76,7 @@ public enum GroundTargetingMode } [PropertyDisplay("Automatic target selection for ground-targeted abilities")] public GroundTargetingMode GTMode = GroundTargetingMode.Manual; + + [PropertyDisplay("Try to prevent dashing into AOEs", tooltip: "Prevent automatic use of damaging gap closers (like WAR Onslaught) if they would move you into a dangerous area. May not work as expected in instances that do not have modules.")] + public bool PreventDangerousDash = false; }