Skip to content

Commit

Permalink
Merge pull request #547 from FFXIV-CombatReborn/NINStuff
Browse files Browse the repository at this point in the history
Ninja fixes
  • Loading branch information
LTS-FFXIV authored Jan 9, 2025
2 parents 8b39b7f + 5dbb5d8 commit ea4dd37
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 51 deletions.
41 changes: 11 additions & 30 deletions BasicRotations/Melee/NIN_Default.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ public sealed class NIN_Default : NinjaRotation

[RotationConfig(CombatType.PvE, Name = "Use Unhide")]
public bool AutoUnhide { get; set; } = true;

[RotationConfig(CombatType.PvE, Name = "Attempt to lock out all GCDs except mudra during mudra to prevent ghosting")]
public bool MudraProtection { get; set; } = false;

public bool IsShadowWalking = Player.HasStatus(true, StatusID.ShadowWalker);
#endregion

#region CountDown Logic
Expand Down Expand Up @@ -104,34 +99,30 @@ private bool ChoiceNinjutsu(out IAction? act)
{
// Attempts to set high-damage AoE Ninjutsu if available under Kassatsu's effect.
// These are prioritized due to Kassatsu's enhancement of Ninjutsu abilities.
if (GokaMekkyakuPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
if (NumberOfHostilesInRange > 2 && GokaMekkyakuPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
{
SetNinjutsu(GokaMekkyakuPvE);
return false;
}
if (HyoshoRanryuPvE.EnoughLevel && TenPvE.CanUse(out _) && JinPvE.CanUse(out _))
if (NumberOfHostilesInRange == 1 && HyoshoRanryuPvE.EnoughLevel && TenPvE.CanUse(out _) && JinPvE.CanUse(out _))
{
SetNinjutsu(HyoshoRanryuPvE);
return false;
}

if (HutonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _) && JinPvE.CanUse(out _))
{
SetNinjutsu(HutonPvE);
return false;
}

if (KatonPvE.EnoughLevel && ChiPvE.CanUse(out _) && TenPvE.CanUse(out _))
{
SetNinjutsu(KatonPvE);
return false;
}

if (RaitonPvE.EnoughLevel && TenPvE.CanUse(out _) && ChiPvE.CanUse(out _))
{
SetNinjutsu(RaitonPvE);
return false;
}
else return false;
}
else
{
Expand Down Expand Up @@ -218,7 +209,7 @@ private bool DoNinjutsu(out IAction? act)
{
if (RaitonPvE_18877.CanUse(out act, skipAoeCheck: true)) return true;
}
else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880) && !Player.HasStatus(true, StatusID.Doton))
else if (chiId == DotonPvE_18880.ID && !IsLastAction(false, DotonPvE_18880) && !HasDoton)
{
if (DotonPvE_18880.CanUse(out act, skipAoeCheck: true)) return true;
}
Expand All @@ -230,7 +221,7 @@ private bool DoNinjutsu(out IAction? act)

//Keep Kassatsu in Burst.
if (!Player.WillStatusEnd(3, false, StatusID.Kassatsu)
&& Player.HasStatus(false, StatusID.Kassatsu) && !InTrickAttack) return false;
&& HasKassatsu && !InTrickAttack) return false;
if (_ninActionAim == null) return false;

var id = AdjustId(ActionID.NinjutsuPvE);
Expand Down Expand Up @@ -316,11 +307,6 @@ protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
// If Ninjutsu is available or not in combat, defers to the base class's emergency ability logic.
if (!NoNinjutsu || !InCombat) return base.EmergencyAbility(nextGCD, out act);

if (NoNinjutsu)
{
if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true;
}

// First priority is given to Kassatsu if it's available, allowing for an immediate powerful Ninjutsu.
if (NoNinjutsu && KassatsuPvE.CanUse(out act)) return true;
if (!TenChiJinPvE.Cooldown.IsCoolingDown && MeisuiPvE.CanUse(out act)) return true;
Expand Down Expand Up @@ -378,7 +364,7 @@ protected override bool AttackAbility(IAction nextGCD, out IAction? act)
// - Not in the Mug's effective window or within Trick Attack's window
// - Certain cooldown conditions are met, or specific statuses are active.
if ((!InMug || InTrickAttack)
&& (!BunshinPvE.Cooldown.WillHaveOneCharge(10) || Player.HasStatus(false, StatusID.PhantomKamaitachiReady) || MugPvE.Cooldown.WillHaveOneCharge(2)))
&& (!BunshinPvE.Cooldown.WillHaveOneCharge(10) || HasPhantomKamaitachi || MugPvE.Cooldown.WillHaveOneCharge(2)))
{
if (HellfrogMediumPvE.CanUse(out act, skipAoeCheck: !BhavacakraPvE.EnoughLevel)) return true;
if (BhavacakraPvE.CanUse(out act)) return true;
Expand All @@ -402,27 +388,22 @@ protected override bool GeneralGCD(out IAction? act)
{
act = null;

var hasRaijuReady = Player.HasStatus(true, StatusID.RaijuReady);

if (RabbitMediumPvE.CanUse(out act)) return true;

if ((InTrickAttack || InMug) && NoNinjutsu && !hasRaijuReady
if ((InTrickAttack || InMug) && NoNinjutsu && !HasRaijuReady
&& !Player.HasStatus(true, StatusID.TenChiJin)
&& PhantomKamaitachiPvE.CanUse(out act)) return true;

if (FleetingRaijuPvE.CanUse(out act)) return true;

if (ChoiceNinjutsu(out act)) return true;
if ((!InCombat || !CombatElapsedLess(7)) && DoNinjutsu(out act)) return true;

//No Ninjutsu
if (NoNinjutsu)
{
if (!CombatElapsedLess(10) && FleetingRaijuPvE.CanUse(out act)) return true;
if (hasRaijuReady) return false;
}

if (IsLastAbility(true, TenPvE, ChiPvE, JinPvE) && MudraProtection)
{
return base.GeneralGCD(out act);
if (HasRaijuReady) return false;
}

//AOE
Expand All @@ -436,7 +417,7 @@ protected override bool GeneralGCD(out IAction? act)
if (SpinningEdgePvE.CanUse(out act)) return true;

//Range
if (!Player.HasStatus(true, StatusID.Mudra))
if (!IsExecutingMudra)
{
if (ThrowingDaggerPvE.CanUse(out act)) return true;
}
Expand Down
2 changes: 1 addition & 1 deletion RotationSolver.Basic/Helpers/ObjectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal static bool CanProvoke(this IGameObject target)
{
foreach (var n in ns1)
{
if (!string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name?.ExtractText() ?? string.Empty).Success)
if (!string.IsNullOrEmpty(n) && new Regex(n).Match(target.Name?.GetText() ?? string.Empty).Success)
{
return false;
}
Expand Down
80 changes: 60 additions & 20 deletions RotationSolver.Basic/Rotations/Basic/NinjaRotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ partial class NinjaRotation
/// <summary>
/// Checks if no ninjutsu action is currently selected or if the Rabbit Medium has been invoked.
/// </summary>
public static bool NoNinjutsu => AdjustId(ActionID.NinjutsuPvE) is ActionID.NinjutsuPvE or ActionID.RabbitMediumPvE;
public static bool NoNinjutsu => !IsExecutingMudra || RabbitMediumPvEActive;

/// <summary>
/// Holds the remaining amount of Delirium stacks
Expand Down Expand Up @@ -121,9 +121,49 @@ public static byte RaijuStacks
/// <summary>
///
/// </summary>
public static bool TenriJindoPvEReady => Service.GetAdjustedActionId(ActionID.TenChiJinPvE) == ActionID.TenriJindoPvE;
public static bool TenriJindoPvEReady => Service.GetAdjustedActionId(ActionID.TenChiJinPvE) == ActionID.TenriJindoPvE && !HasTenChiJin;
#endregion

/// <summary>
///
/// </summary>
public static bool HasKassatsu => !Player.WillStatusEnd(0, true, StatusID.Kassatsu);

/// <summary>
///
/// </summary>
public static bool HasRaijuReady => !Player.WillStatusEnd(0, true, StatusID.RaijuReady);

/// <summary>
///
/// </summary>
public static bool IsExecutingMudra => !Player.WillStatusEnd(0, true, StatusID.Mudra);

/// <summary>
///
/// </summary>
public static bool HasDoton => !Player.WillStatusEnd(0, true, StatusID.Doton);

/// <summary>
///
/// </summary>
public static bool IsShadowWalking => !Player.WillStatusEnd(0, true, StatusID.ShadowWalker);

/// <summary>
///
/// </summary>
public static bool HasPhantomKamaitachi => !Player.WillStatusEnd(0, true, StatusID.PhantomKamaitachiReady);

/// <summary>
///
/// </summary>
public static bool HasTenChiJin => !Player.WillStatusEnd(0, true, StatusID.TenChiJin);

/// <summary>
///
/// </summary>
public static bool IsHidden => !Player.WillStatusEnd(0, true, StatusID.Hidden);

#region Draw Debug
/// <inheritdoc/>
public override void DisplayStatus()
Expand Down Expand Up @@ -277,11 +317,12 @@ static partial void ModifyArmorCrushPvE(ref ActionSetting setting)
static partial void ModifyDreamWithinADreamPvE(ref ActionSetting setting)
{
setting.UnlockedByQuestID = 67222;
setting.ActionCheck = () => !HasTenChiJin;
}

static partial void ModifyHellfrogMediumPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => Ninki >= 50;
setting.ActionCheck = () => Ninki >= 50 && !HasTenChiJin;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
Expand All @@ -292,7 +333,7 @@ static partial void ModifyDokumoriPvE(ref ActionSetting setting)
{
setting.StatusProvide = [StatusID.Higi];
setting.TargetStatusProvide = [StatusID.Dokumori];
setting.ActionCheck = () => Ninki <= 60 && IsLongerThan(10);
setting.ActionCheck = () => Ninki <= 60 && IsLongerThan(10) && !HasTenChiJin;
setting.CreateConfig = () => new ActionConfig()
{
TimeToKill = 10,
Expand All @@ -305,31 +346,32 @@ static partial void ModifyDokumoriPvE(ref ActionSetting setting)

static partial void ModifyBhavacakraPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => Ninki >= 50;
setting.ActionCheck = () => Ninki >= 50 && !HasTenChiJin;
}

static partial void ModifyTenChiJinPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => !HasKassatsu;
setting.StatusProvide = [StatusID.TenChiJin, StatusID.TenriJindoReady];
setting.UnlockedByQuestID = 68488;
}

static partial void ModifyMeisuiPvE(ref ActionSetting setting)
{
setting.StatusNeed = [StatusID.ShadowWalker];
setting.StatusProvide = [StatusID.Meisui];
setting.ActionCheck = () => !Player.HasStatus(true, StatusID.Kassatsu) && InCombat;
setting.ActionCheck = () => !HasKassatsu && InCombat && !HasTenChiJin;
}

static partial void ModifyBunshinPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => Ninki >= 50;
setting.ActionCheck = () => Ninki >= 50 && !HasTenChiJin;
setting.StatusProvide = [StatusID.Bunshin, StatusID.PhantomKamaitachiReady];
}

static partial void ModifyPhantomKamaitachiPvE(ref ActionSetting setting)
{
setting.StatusNeed = [StatusID.PhantomKamaitachiReady];
setting.ActionCheck = () => HasPhantomKamaitachi;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
Expand All @@ -338,7 +380,7 @@ static partial void ModifyPhantomKamaitachiPvE(ref ActionSetting setting)

static partial void ModifyHollowNozuchiPvE(ref ActionSetting setting)
{
setting.StatusNeed = [StatusID.Doton];
setting.ActionCheck = () => HasDoton;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 1,
Expand All @@ -347,17 +389,17 @@ static partial void ModifyHollowNozuchiPvE(ref ActionSetting setting)

static partial void ModifyForkedRaijuPvE(ref ActionSetting setting)
{
setting.StatusNeed = [StatusID.RaijuReady];
setting.ActionCheck = () => HasRaijuReady;
}

static partial void ModifyFleetingRaijuPvE(ref ActionSetting setting)
{
setting.StatusNeed = [StatusID.RaijuReady];
setting.ActionCheck = () => HasRaijuReady;
}

static partial void ModifyKunaisBanePvE(ref ActionSetting setting)
{
setting.ActionCheck = () => Player.HasStatus(true, StatusID.Hidden) || Player.HasStatus(true, StatusID.ShadowWalker);
setting.ActionCheck = () => (IsHidden || IsShadowWalking) && !HasTenChiJin;
setting.TargetStatusProvide = [StatusID.KunaisBane];
setting.CreateConfig = () => new ActionConfig()
{
Expand All @@ -367,7 +409,7 @@ static partial void ModifyKunaisBanePvE(ref ActionSetting setting)

static partial void ModifyDeathfrogMediumPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => Ninki <= 50 && DeathfrogMediumPvEReady;
setting.ActionCheck = () => Ninki <= 50 && DeathfrogMediumPvEReady && !HasTenChiJin;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
Expand All @@ -376,7 +418,7 @@ static partial void ModifyDeathfrogMediumPvE(ref ActionSetting setting)

static partial void ModifyZeshoMeppoPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => Ninki <= 50 && ZeshoMeppoPvEReady;
setting.ActionCheck = () => Ninki <= 50 && ZeshoMeppoPvEReady && !HasTenChiJin;
}

static partial void ModifyTenriJindoPvE(ref ActionSetting setting)
Expand Down Expand Up @@ -426,13 +468,11 @@ static partial void ModifyRaitonPvE(ref ActionSetting setting)
static partial void ModifyHyotonPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => HyotonPvEReady;
setting.TargetStatusProvide = [StatusID.Blind];
}

static partial void ModifyHutonPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => HutonPvEReady;
setting.StatusProvide = [StatusID.ShadowWalker];
setting.ActionCheck = () => HutonPvEReady && !IsShadowWalking;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
Expand All @@ -457,7 +497,7 @@ static partial void ModifySuitonPvE(ref ActionSetting setting)

static partial void ModifyGokaMekkyakuPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => GokaMekkyakuPvEReady;
setting.ActionCheck = () => HasKassatsu;
setting.CreateConfig = () => new ActionConfig()
{
AoeCount = 3,
Expand All @@ -466,7 +506,7 @@ static partial void ModifyGokaMekkyakuPvE(ref ActionSetting setting)

static partial void ModifyHyoshoRanryuPvE(ref ActionSetting setting)
{
setting.ActionCheck = () => HyoshoRanryuPvEReady;
setting.ActionCheck = () => HasKassatsu;
}
#endregion

Expand Down

0 comments on commit ea4dd37

Please sign in to comment.