private static async Task <bool> ProcessCardLogic(CardLogicType logictype, CardPlayType playtype, AstrologianCard card) { if (AstrologianSettings.Instance.CardRules == null) { return(false); } //if (TimeSinceTheLastCardAction < LastCardThreshold) return false; if (!LastCardAction.CanCastNewAction) { return(false); } var ruleincombat = Core.Me.InCombat; var cardRulesToProcess = AstrologianSettings.Instance.CardRules.Where(r => r.Card == card && r.LogicType == logictype && r.PlayType == playtype).OrderBy(r => r.CardPriority); return(await ProcessCardRule(cardRulesToProcess, ruleincombat, playtype, logictype)); }
private static async Task <bool> ProcessCardRule(IEnumerable <CardRule> cardRulesToProcess, bool ruleincombat, CardPlayType playtype, CardLogicType logictype) { if (cardRulesToProcess == null) { return(false); } var rulesToProcess = cardRulesToProcess as IList <CardRule> ?? cardRulesToProcess.ToList(); var heldcard = HeldCard(); var processed = false; //Logger.WriteInfo($@"Processing up to {rulesToProcess.Count} {logictype} rules"); foreach (var cardRule in rulesToProcess) { //Logger.WriteInfo($"Processing rule: {cardRule.CardPriority}"); //For testing that the card rule processing is going by priority await Coroutine.Yield(); if (processed) { Logger.WriteInfo($"Detected that we've already processed a rule for {cardRule.Card}"); return(true); } if (playtype == CardPlayType.Drawn && cardRule.Card != DrawnCard()) { return(false); } if (playtype == CardPlayType.Held && cardRule.Card != HeldCard()) { return(false); } var action = cardRule.Action; // ReSharper disable once SuggestVarOrType_SimpleTypes Conditions conditions = cardRule.Conditions; var targetrule = cardRule.Target; CardTargets.Clear(); GameObject target = Core.Me; // ReSharper disable once SuggestVarOrType_SimpleTypes TargetConditions targetconditions = cardRule.TargetConditions; if (conditions != null) { //if (cardRule.CardPriority == 33) Logger.WriteInfo($"InCombat Check"); if (conditions.InCombat != null && conditions.InCombat != ruleincombat) { continue; } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"HasHeldCard Check"); if (conditions.HasHeldCard?.Count > 0) { if (conditions.HasHeldCard.All(r => r != heldcard)) { continue; } } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"DoesntHaveHeldCard Check"); if (conditions.DoesntHaveHeldCard?.Count > 0) { if (conditions.DoesntHaveHeldCard.Any(r => r == heldcard)) { continue; } } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"JobsInParty Check"); if (conditions.JobsNotInParty?.Count > 0 && Globals.InParty) { if (PartyManager.AllMembers.Any(r => conditions.JobsNotInParty.Contains(r.Class))) { continue; } } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"RolesNotInParty Check"); if (conditions.RolesNotInParty?.Count > 0 && Globals.InParty) { if (PartyManager.AllMembers.Any(r => (conditions.RolesNotInParty.Contains(CardRole.Tank) && r.GameObject.IsTank()) || (conditions.RolesNotInParty.Contains(CardRole.Healer) && r.GameObject.IsHealer()) || (conditions.RolesNotInParty.Contains(CardRole.Dps) && r.GameObject.IsDps()))) { continue; } } } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"Building Target List"); if (targetrule == CardTarget.Me) { CardTargets.Add(Core.Me); } if (targetrule == CardTarget.PartyMember) { CardTargets = PartyManager.VisibleMembers.Select(r => r.BattleCharacter).Where(r => r.IsTargetable && r.InLineOfSight() && r.Icon != PlayerIcon.Viewing_Cutscene).ToList(); } //if (cardRule.CardPriority == 33) Logger.WriteInfo($@"Processing Card Action: {action} on: {target}"); switch (action) { case CardAction.Redraw: if (!CanRedraw) { continue; } if (!await Spells.Redraw.Cast(Core.Me)) { return(false); } LogRuleProcessed(cardRule, ruleincombat, heldcard); processed = true; return(true); case CardAction.MinorArcana: if (!CanMinorArcana) { continue; } if (!await Spells.MinorArcana.Cast(Core.Me)) { return(false); } LogRuleProcessed(cardRule, ruleincombat, heldcard); processed = true; return(true); case CardAction.Play: { //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets Starting Count: {CardTargets.Count()}"); CardTargets.RemoveAll(r => r.HasCardAura() || r.CurrentHealth < 1 || r.IsDead || !r.IsValid); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After Death Clean: {CardTargets.Count()}"); if (targetconditions != null) { var statLessThanFlag = false; if (targetconditions.MpLessThan != null && targetconditions.MpLessThan > 0 && targetconditions.MpLessThan < 100) { CardTargets.RemoveAll(r => r.CurrentManaPercent > targetconditions.MpLessThan); CardTargets = CardTargets.OrderBy(r => r.CurrentManaPercent).ToList(); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After MP Clean: {CardTargets.Count()}"); statLessThanFlag = true; } if (targetconditions.HpLessThan != null && targetconditions.HpLessThan > 0 && targetconditions.HpLessThan < 100) { CardTargets.RemoveAll(r => r.CurrentHealthPercent > targetconditions.HpLessThan); CardTargets = CardTargets.OrderBy(r => r.CurrentHealthPercent).ToList(); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After HP Clean: {CardTargets.Count()}"); statLessThanFlag = true; } if (targetconditions.HasTarget != null) { CardTargets.RemoveAll(r => r.HasTarget != targetconditions.HasTarget); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After Has Target Clean: {CardTargets.Count()}"); } if (targetconditions.IsRole?.Count > 0) { //if (cardRule.CardPriority == 33) Logger.WriteInfo($"Comparing IsRole Clean: {targetconditions.IsRole.Select(r => r.ToString())}"); if (targetconditions.IsRole.All(r => r != CardRole.Dps)) { CardTargets.RemoveAll(r => r.IsDps()); } if (targetconditions.IsRole.All(r => r != CardRole.Tank)) { CardTargets.RemoveAll(r => r.IsTank()); } if (targetconditions.IsRole.All(r => r != CardRole.Healer)) { CardTargets.RemoveAll(r => r.IsHealer()); } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After IsRole Clean: {CardTargets.Count()}"); } if (targetconditions.IsJob?.Count > 0) { //if (cardRule.CardPriority == 33) Logger.WriteInfo($"Comparing IsJob Clean: {targetconditions.IsJob.Select(r => r.ToString())}"); CardTargets.RemoveAll(r => !targetconditions.IsJob.Contains(r.CurrentJob)); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After IsJob Clean: {CardTargets.Count()}"); } if (targetconditions.JobOrder != null) { CardTargets = CardTargets.OrderBy(x => { var index = targetconditions.JobOrder.IndexOf(x.CurrentJob); if (index == -1) { index = int.MaxValue; } return(index); }).ToList(); statLessThanFlag = true; } if (targetconditions.WithAlliesNearbyMoreThan != null && targetconditions.WithAlliesNearbyMoreThan > 0) { CardTargets.RemoveAll(r => r.PartyMembersNearby(15).Count() <= targetconditions.WithAlliesNearbyMoreThan); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets After WithAlliesNearbyMoreThan Clean: {CardTargets.Count()}"); } if (targetrule == CardTarget.PartyMember) { if (targetconditions.PlayerName != null) { target = CardTargets.FirstOrDefault(r => r.Name == targetconditions.PlayerName); } else if ((targetconditions.Choice == CardChoiceType.Random || targetconditions.Choice == null) && !statLessThanFlag) { var random = new Random(); target = CardTargets.ElementAtOrDefault(random.Next(0, CardTargets.Count)); } else { target = CardTargets.FirstOrDefault(); } if (target == null) { //if (cardRule.CardPriority == 33) Logger.WriteInfo($"No Viable Target based on Conditions"); continue; } } } //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets Ending Count: {CardTargets.Count()}"); //if (cardRule.CardPriority == 33) Logger.WriteInfo($"CardTargets Attempting to use {cardRule.Card} on {target}"); switch (playtype) { case CardPlayType.Drawn: if (logictype == CardLogicType.Pvp) { //Logger.WriteInfo($@"Trying to Pvp Play Drawn {cardRule.Card} on {target.Name} (CanAttack: {target.CanAttack})"); if (!await Spells.PvpPlayDrawn.Cast(target)) { return(false); } LogRuleProcessed(cardRule, ruleincombat, heldcard); processed = true; return(true); } //if (cardRule.CardPriority == 33) Logger.WriteInfo($@"Trying to Normal Play Drawn {cardRule.Card} on {target.Name} (CanAttack: {target.CanAttack})"); if (!await Spells.PlayDrawn.Cast(target)) { return(false); } LogRuleProcessed(cardRule, ruleincombat, heldcard); processed = true; return(true); case CardPlayType.Held: if (!await Spells.PlaySpread.Cast(target)) { return(false); } LogRuleProcessed(cardRule, ruleincombat, heldcard); processed = true; return(true); default: processed = true; return(false); } } case CardAction.StopLogic: processed = true; return(false); case CardAction.Undraw: if (!CanUndraw) { continue; } if (!await Spells.Undraw.Cast(Core.Me)) { return(false); } LogRuleProcessed(cardRule, ruleincombat, heldcard); processed = true; return(true); default: continue; } } if (playtype != CardPlayType.Drawn || logictype == CardLogicType.Pvp) { return(false); } var drawncard = DrawnCard(); if (AstrologianSettings.Instance.CardRuleDefaultToMinorArcana && CanMinorArcana) { if (!await Spells.MinorArcana.Cast(Core.Me)) { return(false); } if (BaseSettings.Instance.DebugPlayerCasting) { Logger.WriteInfo($"No appropriate Card Rule to process. Using Minor Arcana on {drawncard} for Lord Of Crowns."); } processed = true; return(true); } if (!AstrologianSettings.Instance.CardRuleDefaultToUndraw) { return(false); } if (!CanUndraw) { return(false); } if (!await Spells.Undraw.Cast(Core.Me)) { return(false); } if (BaseSettings.Instance.DebugPlayerCasting) { Logger.WriteInfo($"No appropriate Card Rule to process. Undrawing {drawncard}."); } processed = true; return(true); }