Skip to content

Commit c67ff2f

Browse files
authored
Merge pull request #966 from FFXIV-CombatReborn/theproblemchildren
brickfix for Ninja and Sage
2 parents 6289556 + 3c315a6 commit c67ff2f

File tree

2 files changed

+156
-68
lines changed

2 files changed

+156
-68
lines changed

RotationSolver/RebornRotations/Healer/SGE_Reborn.cs

Lines changed: 151 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -428,45 +428,40 @@ private bool ChoiceEukrasia(out IAction? act)
428428
{
429429
act = null;
430430

431-
if (!EukrasiaPvE.CanUse(out _))
432-
{
433-
return false;
434-
}
435-
436-
// Checks for Eukrasia status.
437-
// Attempts to set correct Eurkrasia action based on availability and MergedStatus.
431+
// Only decide the aim; do not require Eukrasia to be currently usable here.
432+
// Attempts to set correct Eukrasia action based on availability and MergedStatus.
438433
if (EukrasianPrognosisIiPvE.EnoughLevel && EukrasianPrognosisIiPvE.IsEnabled && MergedStatus.HasFlag(AutoStatus.DefenseArea)
439-
&& EukrasianPrognosisIiPvE.CanUse(out _))
434+
&& EukrasianPrognosisIiPvE.CanUse(out _, skipStatusNeed: true))
440435
{
441436
SetEukrasia(EukrasianPrognosisIiPvE);
442437
}
443438
else if (!EukrasianPrognosisIiPvE.EnoughLevel && EukrasianPrognosisPvE.EnoughLevel && EukrasianPrognosisPvE.IsEnabled && MergedStatus.HasFlag(AutoStatus.DefenseArea)
444-
&& EukrasianPrognosisPvE.CanUse(out _))
439+
&& EukrasianPrognosisPvE.CanUse(out _, skipStatusNeed: true))
445440
{
446441
SetEukrasia(EukrasianPrognosisPvE);
447442
}
448443
else if (EukrasianDiagnosisPvE.EnoughLevel && EukrasianDiagnosisPvE.IsEnabled && MergedStatus.HasFlag(AutoStatus.DefenseSingle)
449-
&& EukrasianDiagnosisPvE.CanUse(out _))
444+
&& EukrasianDiagnosisPvE.CanUse(out _, skipStatusNeed: true))
450445
{
451446
SetEukrasia(EukrasianDiagnosisPvE);
452447
}
453448
else if (EukrasianDyskrasiaPvE.EnoughLevel && EukrasianDyskrasiaPvE.IsEnabled && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea))
454-
&& EukrasianDyskrasiaPvE.CanUse(out _))
449+
&& EukrasianDyskrasiaPvE.CanUse(out _, skipStatusNeed: true))
455450
{
456451
SetEukrasia(EukrasianDyskrasiaPvE);
457452
}
458-
else if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _))
459-
&& EukrasianDosisIiiPvE.CanUse(out _) && EukrasianDosisIiiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea)) && EukrasianDosisIiiPvE.IsEnabled)
453+
else if ((!EukrasianDyskrasiaPvE.CanUse(out _, skipStatusNeed: true) || !DyskrasiaPvE.CanUse(out _))
454+
&& EukrasianDosisIiiPvE.CanUse(out _, skipStatusNeed: true) && EukrasianDosisIiiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea)) && EukrasianDosisIiiPvE.IsEnabled)
460455
{
461456
SetEukrasia(EukrasianDosisIiiPvE);
462457
}
463-
else if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _))
464-
&& EukrasianDosisIiPvE.CanUse(out _) && !EukrasianDosisIiiPvE.EnoughLevel && EukrasianDosisIiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea)) && EukrasianDosisIiPvE.IsEnabled)
458+
else if ((!EukrasianDyskrasiaPvE.CanUse(out _, skipStatusNeed: true) || !DyskrasiaPvE.CanUse(out _))
459+
&& EukrasianDosisIiPvE.CanUse(out _, skipStatusNeed: true) && !EukrasianDosisIiiPvE.EnoughLevel && EukrasianDosisIiPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea)) && EukrasianDosisIiPvE.IsEnabled)
465460
{
466461
SetEukrasia(EukrasianDosisIiPvE);
467462
}
468-
else if ((!EukrasianDyskrasiaPvE.CanUse(out _) || !DyskrasiaPvE.CanUse(out _))
469-
&& EukrasianDosisPvE.CanUse(out _) && !EukrasianDosisIiPvE.EnoughLevel && EukrasianDosisPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea)) && EukrasianDosisPvE.IsEnabled)
463+
else if ((!EukrasianDyskrasiaPvE.CanUse(out _, skipStatusNeed: true) || !DyskrasiaPvE.CanUse(out _))
464+
&& EukrasianDosisPvE.CanUse(out _, skipStatusNeed: true) && !EukrasianDosisIiPvE.EnoughLevel && EukrasianDosisPvE.EnoughLevel && (!MergedStatus.HasFlag(AutoStatus.DefenseSingle) && !MergedStatus.HasFlag(AutoStatus.DefenseArea)) && EukrasianDosisPvE.IsEnabled)
470465
{
471466
SetEukrasia(EukrasianDosisPvE);
472467
}
@@ -481,19 +476,53 @@ private bool ChoiceEukrasia(out IAction? act)
481476

482477
#region Eukrasia Execution
483478
// Attempts to perform a Eukrasia action, based on the current game state and conditions.
484-
private bool DoEukrasianPrognosis(out IAction? act)
479+
private bool DoEukrasianPrognosisIi(out IAction? act)
485480
{
486481
act = null;
487482

488-
if (_EukrasiaActionAim != null && (_EukrasiaActionAim == EukrasianPrognosisPvE || _EukrasiaActionAim == EukrasianPrognosisIiPvE) && _EukrasiaActionAim.CanUse(out _))
483+
if (_EukrasiaActionAim != null &&
484+
_EukrasiaActionAim == EukrasianPrognosisIiPvE)
489485
{
490-
if (EukrasiaPvE.CanUse(out act))
486+
// If we don't have Eukrasia, press it first to enable the Eukrasian spell.
487+
if (!HasEukrasia)
488+
{
489+
if (EukrasiaPvE.CanUse(out act))
490+
{
491+
return true;
492+
}
493+
return false;
494+
}
495+
496+
if (EukrasianPrognosisIiPvE.CanUse(out act))
491497
{
492498
return true;
493499
}
500+
}
501+
return false;
502+
}
503+
504+
// Attempts to perform a Eukrasia action, based on the current game state and conditions.
505+
private bool DoEukrasianPrognosis(out IAction? act)
506+
{
507+
act = null;
508+
509+
if (_EukrasiaActionAim != null &&
510+
_EukrasiaActionAim == EukrasianPrognosisPvE)
511+
{
512+
// If we don't have Eukrasia, press it first to enable the Eukrasian spell.
513+
if (!HasEukrasia)
514+
{
515+
if (EukrasiaPvE.CanUse(out act))
516+
{
517+
return true;
518+
}
519+
return false;
520+
}
494521

495-
act = _EukrasiaActionAim;
496-
return true;
522+
if (EukrasianPrognosisPvE.CanUse(out act))
523+
{
524+
return true;
525+
}
497526
}
498527
return false;
499528
}
@@ -503,15 +532,21 @@ private bool DoEukrasianDiagnosis(out IAction? act)
503532
{
504533
act = null;
505534

506-
if (_EukrasiaActionAim != null && _EukrasiaActionAim == EukrasianDiagnosisPvE && EukrasianDiagnosisPvE.CanUse(out _))
535+
if (_EukrasiaActionAim != null && _EukrasiaActionAim == EukrasianDiagnosisPvE)
507536
{
508-
if (EukrasiaPvE.CanUse(out act))
537+
if (!HasEukrasia)
509538
{
510-
return true;
539+
if (EukrasiaPvE.CanUse(out act))
540+
{
541+
return true;
542+
}
543+
return false;
511544
}
512545

513-
act = _EukrasiaActionAim;
514-
return true;
546+
if (EukrasianDiagnosisPvE.CanUse(out act))
547+
{
548+
return true;
549+
}
515550
}
516551
return false;
517552
}
@@ -521,33 +556,94 @@ private bool DoEukrasianDyskrasia(out IAction? act)
521556
{
522557
act = null;
523558

524-
if (_EukrasiaActionAim != null && _EukrasiaActionAim == EukrasianDyskrasiaPvE && EukrasianDyskrasiaPvE.CanUse(out _))
559+
if (_EukrasiaActionAim != null && _EukrasiaActionAim == EukrasianDyskrasiaPvE)
525560
{
526-
if (EukrasiaPvE.CanUse(out act))
561+
if (!HasEukrasia)
527562
{
528-
return true;
563+
if (EukrasiaPvE.CanUse(out act))
564+
{
565+
return true;
566+
}
567+
return false;
529568
}
530569

531-
act = _EukrasiaActionAim;
532-
return true;
570+
if (EukrasianDyskrasiaPvE.CanUse(out act))
571+
{
572+
return true;
573+
}
533574
}
534575
return false;
535576
}
536577

537578
// Attempts to perform a Eukrasia action, based on the current game state and conditions.
538-
private bool DoEukrasianDosis(out IAction? act)
579+
private bool DoEukrasianDosisIii(out IAction? act)
580+
{
581+
act = null;
582+
583+
if (_EukrasiaActionAim != null &&
584+
_EukrasiaActionAim == EukrasianDosisIiiPvE)
585+
{
586+
if (!HasEukrasia)
587+
{
588+
if (EukrasiaPvE.CanUse(out act))
589+
{
590+
return true;
591+
}
592+
return false;
593+
}
594+
595+
if (EukrasianDosisIiiPvE.CanUse(out act))
596+
{
597+
return true;
598+
}
599+
}
600+
return false;
601+
}
602+
603+
private bool DoEukrasianDosisIi(out IAction? act)
539604
{
540605
act = null;
541606

542-
if (_EukrasiaActionAim != null && (_EukrasiaActionAim == EukrasianDosisPvE || _EukrasiaActionAim == EukrasianDosisIiPvE || _EukrasiaActionAim == EukrasianDosisIiiPvE) && _EukrasiaActionAim.CanUse(out _))
607+
if (_EukrasiaActionAim != null &&
608+
_EukrasiaActionAim == EukrasianDosisIiPvE)
543609
{
544-
if (EukrasiaPvE.CanUse(out act))
610+
if (!HasEukrasia)
611+
{
612+
if (EukrasiaPvE.CanUse(out act))
613+
{
614+
return true;
615+
}
616+
return false;
617+
}
618+
619+
if (EukrasianDosisIiPvE.CanUse(out act))
545620
{
546621
return true;
547622
}
623+
}
624+
return false;
625+
}
548626

549-
act = _EukrasiaActionAim;
550-
return true;
627+
private bool DoEukrasianDosis(out IAction? act)
628+
{
629+
act = null;
630+
631+
if (_EukrasiaActionAim != null &&
632+
_EukrasiaActionAim == EukrasianDosisPvE)
633+
{
634+
if (!HasEukrasia)
635+
{
636+
if (EukrasiaPvE.CanUse(out act))
637+
{
638+
return true;
639+
}
640+
return false;
641+
}
642+
643+
if (EukrasianDosisPvE.CanUse(out act))
644+
{
645+
return true;
646+
}
551647
}
552648
return false;
553649
}
@@ -557,10 +653,9 @@ private bool DoEukrasianDosis(out IAction? act)
557653
[RotationDesc(ActionID.PneumaPvE, ActionID.PrognosisPvE, ActionID.EukrasianPrognosisPvE, ActionID.EukrasianPrognosisIiPvE)]
558654
protected override bool HealAreaGCD(out IAction? act)
559655
{
560-
act = null;
561656
if (IsLastAction(ActionID.SwiftcastPvE) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise))
562657
{
563-
return false;
658+
return base.HealAreaGCD(out act);
564659
}
565660

566661
bool tankBelowThreshold = false;
@@ -603,10 +698,9 @@ protected override bool HealAreaGCD(out IAction? act)
603698
[RotationDesc(ActionID.DiagnosisPvE, ActionID.EukrasianDiagnosisPvE)]
604699
protected override bool HealSingleGCD(out IAction? act)
605700
{
606-
act = null;
607701
if (IsLastAction(ActionID.SwiftcastPvE) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise))
608702
{
609-
return false;
703+
return base.HealSingleGCD(out act);
610704
}
611705

612706
if (HasEukrasia && EukrasiaActionHeal && EukrasianDiagnosisPvE.CanUse(out act))
@@ -629,10 +723,14 @@ protected override bool HealSingleGCD(out IAction? act)
629723

630724
protected override bool GeneralGCD(out IAction? act)
631725
{
632-
act = null;
633726
if (IsLastAction(ActionID.SwiftcastPvE) && SwiftLogic && MergedStatus.HasFlag(AutoStatus.Raise))
634727
{
635-
return false;
728+
return base.GeneralGCD(out act);
729+
}
730+
731+
if (DoEukrasianPrognosisIi(out act))
732+
{
733+
return true;
636734
}
637735

638736
if (DoEukrasianPrognosis(out act))
@@ -688,6 +786,16 @@ protected override bool GeneralGCD(out IAction? act)
688786
return true;
689787
}
690788

789+
if (DoEukrasianDosisIii(out act))
790+
{
791+
return true;
792+
}
793+
794+
if (DoEukrasianDosisIi(out act))
795+
{
796+
return true;
797+
}
798+
691799
if (DoEukrasianDosis(out act))
692800
{
693801
return true;

RotationSolver/RebornRotations/Melee/NIN_Reborn.cs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -108,24 +108,22 @@ protected override bool MoveForwardGCD(out IAction? act)
108108
// Determines the emergency abilities to use, overriding the base class implementation.
109109
protected override bool EmergencyAbility(IAction nextGCD, out IAction? act)
110110
{
111-
// Initializes the action to null, indicating no action has been chosen yet.
112-
113111
// If the last action performed matches any of a list of specific actions, it clears the Ninjutsu aim.
114112
// This serves as a reset/cleanup mechanism to ensure the decision logic starts fresh for the next cycle.
115113
if (IsLastAction(false, FumaShurikenPvE, KatonPvE, RaitonPvE, HyotonPvE, DotonPvE, SuitonPvE)
116114
|| (IsShadowWalking && (_ninActionAim == SuitonPvE || _ninActionAim == HutonPvE))
117115
|| (_ninActionAim == GokaMekkyakuPvE && IsLastGCD(false, GokaMekkyakuPvE))
118116
|| (_ninActionAim == HyoshoRanryuPvE && IsLastGCD(false, HyoshoRanryuPvE))
119117
|| (_ninActionAim == GokaMekkyakuPvE && !HasKassatsu)
120-
|| (_ninActionAim == HyoshoRanryuPvE && !HasKassatsu)
121-
|| IsLastAction(false, KassatsuPvE))
118+
|| (_ninActionAim == HyoshoRanryuPvE && !HasKassatsu))
122119
{
123120
ClearNinjutsu();
124121
}
125122

126-
if ((InCombat || (CombatMudra && HasHostilesInMaxRange && TenPvE.Cooldown.CurrentCharges == TenPvE.Cooldown.MaxCharges)) && ChoiceNinjutsu(out act))
123+
// Side-effect: decide/refresh ninjutsu aim; do not consume the oGCD slot here.
124+
if (InCombat || (CombatMudra && HasHostilesInMaxRange && TenPvE.Cooldown.CurrentCharges == TenPvE.Cooldown.MaxCharges))
127125
{
128-
return true;
126+
_ = ChoiceNinjutsu(out _);
129127
}
130128

131129
if (!InCombat && !CombatMudra)
@@ -313,18 +311,9 @@ private bool ChoiceNinjutsu(out IAction? act)
313311
{
314312
act = null;
315313

316-
// Ensures that the action ID currently considered for Ninjutsu is actually valid for Ninjutsu execution.
317-
//if (AdjustId(ActionID.NinjutsuPvE) != ActionID.NinjutsuPvE) return false;
318-
// If more than 4.5 seconds have passed since the last action, it clears any pending Ninjutsu to avoid stale actions.
319-
320-
//if (TimeSinceLastAction.TotalSeconds > 4.5 ) ClearNinjutsu();
321-
//-- This has been commented out for now as it breaks ninjustsu decision making at the beginning of combat, need to find better implementation.
322-
323314
// Checks for Kassatsu status to prioritize high-impact Ninjutsu due to its buff.
324315
if (Player.HasStatus(true, StatusID.Kassatsu))
325316
{
326-
// Attempts to set high-damage AoE Ninjutsu if available under Kassatsu's effect.
327-
// These are prioritized due to Kassatsu's enhancement of Ninjutsu abilities.
328317
if ((DeathBlossomPvE.CanUse(out _) || HakkeMujinsatsuPvE.CanUse(out _)) && GokaMekkyakuPvE.EnoughLevel && !IsLastAction(false, GokaMekkyakuPvE) && GokaMekkyakuPvE.IsEnabled)
329318
{
330319
SetNinjutsu(GokaMekkyakuPvE);
@@ -355,10 +344,6 @@ private bool ChoiceNinjutsu(out IAction? act)
355344
}
356345
else if (TenPvE.CanUse(out _, usedUp: ShadowWalkerNeeded || InTrickAttack || TenPvE.Cooldown.WillHaveXChargesGCD(2, 2, 0)) && _ninActionAim == null)
357346
{
358-
// Chooses buffs or AoE actions based on combat conditions and cooldowns.
359-
// For instance, setting Huton for speed buff or choosing AoE Ninjutsu like Katon or Doton based on enemy positioning.
360-
// Also considers using Suiton for vulnerability debuff on the enemy if conditions are optimal.
361-
362347
//Vulnerable
363348
if (ShadowWalkerNeeded && (!MeisuiPvE.Cooldown.IsCoolingDown || !TrickAttackPvE.Cooldown.IsCoolingDown || KunaisBanePvE.Cooldown.IsCoolingDown) && !IsShadowWalking && !HasTenChiJin && SuitonPvE.EnoughLevel)
364349
{
@@ -987,11 +972,6 @@ protected override bool GeneralGCD(out IAction? act)
987972
return true;
988973
}
989974

990-
if (DoHuton(out act))
991-
{
992-
return true;
993-
}
994-
995975
if (DoHyoton(out act))
996976
{
997977
return true;
@@ -1099,4 +1079,4 @@ public override bool IsBursting()
10991079
}
11001080
return false;
11011081
}
1102-
}
1082+
}

0 commit comments

Comments
 (0)