public EngineAction Run(CureConfig Config, bool[] enabledMembers, bool[] highPriorityMembers) { _config = Config; IEnumerable <PartyMember> partyByHP = Monitored.GetActivePartyMembers().OrderBy(member => member.CurrentHPP); /////////////////////////// PL CURE ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: Test this! Pretty sure your own character is always party member index 0. if (PL.Player.HP > 0 && (PL.Player.HPP <= Config.MonitoredCurePercentage) && Config.EnableOutOfPartyHealing && !PL.SamePartyAs(Monitored)) { var plAsPartyMember = PL.Party.GetPartyMember(0); return(CureCalculator(plAsPartyMember)); } /////////////////////////// CURAGA ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if (Config.EnabledCuragaTiers.Any()) { int plParty = PL.GetPartyRelativeTo(Monitored); // Order parties that qualify for AOE cures by average missing HP. var partyNeedsAoe = Monitored.PartyNeedsAoeCure(Config.CuragaMinPlayers, Config.CuragaHealthPercent).OrderBy(partyNumber => Monitored.AverageHpLossForParty(partyNumber)); // If PL is in same alliance, and there's at least 1 party that needs an AOE cure. // Parties are ordered by most average missing HP. if (plParty > 0 && partyNeedsAoe.Any()) { int targetParty = 0; // We can accession if we have light arts/addendum white, and either we already have the status or we have the ability available, // and have the charges to use it. bool plCanAccession = (PL.HasStatus(StatusEffect.Light_Arts) || PL.HasStatus(StatusEffect.Addendum_White)) && (PL.HasStatus(StatusEffect.Accession) || (PL.AbilityAvailable(Ability.Accession) && PL.CurrentSCHCharges() > 0)); foreach (int party in partyNeedsAoe) { // We check whether we can accession here, so that if we can't accession we don't skip a chance to curaga our own party. if (party != plParty && !plCanAccession) { continue; } // We get the first party with at least 1 person who's in it and checked. // As well as 1 person who's both under the cure threshold AND in casting range. // This way we won't AOE parties we haven't got anyone checked in, and we won't attempt // to AOE a party where we can't reach any of the injured members. if (partyByHP.Count(pm => pm.InParty(party) && enabledMembers[pm.MemberNumber]) > 0) { if (partyByHP.Count(pm => pm.InParty(party) && pm.CurrentHPP < Config.CuragaHealthPercent && PL.CanCastOn(pm)) > 0) { targetParty = party; } } } if (targetParty > 0) { // The target is the first person we can cast on, since they're already ordered by HPP. var target = partyByHP.FirstOrDefault(pm => pm.InParty(targetParty) && PL.CanCastOn(pm)); if (target != default) { // If same party as PL, curaga. Otherwise we try to accession cure. if (targetParty == plParty) { // TODO: Don't do this if we have no curagas enabled, prevents curing! return(CuragaCalculator(target)); } else { var actionResult = CureCalculator(target); // We've already determined we can accession, or already have the status. if (actionResult != null && !PL.HasStatus(StatusEffect.Accession)) { actionResult.JobAbility = Ability.Accession; } return(actionResult); } } } } } /////////////////////////// CURE ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // First run a check on the monitored target if (Config.MonitoredPriorityEnabled && Monitored.Player.HP > 0 && (Monitored.Player.HPP <= Config.MonitoredCurePercentage)) { // Need to get monitored player as a PartyMember PartyMember monitoredPlayer = partyByHP.FirstOrDefault(p => p.Name == Monitored.Player.Name); if (monitoredPlayer != default) { return(CureCalculator(monitoredPlayer)); } } // Calculate who needs a cure, and is a valid target. // Anyone who's: Enabled + Active + Alive + Under cure threshold var validCures = partyByHP.Where(pm => enabledMembers[pm.MemberNumber] && (pm.CurrentHPP <= Config.CureHealthPercent) && PL.CanCastOn(pm)); // Now run a scan to check all targets in the High Priority Threshold if (validCures != null && validCures.Any()) { var highPriorityCures = validCures.Where(pm => highPriorityMembers[pm.MemberNumber]); if (highPriorityCures != null && highPriorityCures.Any()) { return(CureCalculator(highPriorityCures.First())); } else { return(CureCalculator(validCures.First())); } } return(null); }