From 27ff63d400a662ffeb0ca5e883d026fa0c5f324b Mon Sep 17 00:00:00 2001 From: Joshua Thome Date: Sun, 16 Feb 2025 16:46:47 -0600 Subject: [PATCH] Component to process conditional checks --- .../Conditionals/ConditionalsManager.cs | 83 +++++++++++++++++++ .../PlayerPatches/PlayerDataPatches.cs | 8 ++ 2 files changed, 91 insertions(+) create mode 100644 NewHorizons/Components/Conditionals/ConditionalsManager.cs diff --git a/NewHorizons/Components/Conditionals/ConditionalsManager.cs b/NewHorizons/Components/Conditionals/ConditionalsManager.cs new file mode 100644 index 00000000..0f301e7b --- /dev/null +++ b/NewHorizons/Components/Conditionals/ConditionalsManager.cs @@ -0,0 +1,83 @@ +using NewHorizons.External.Modules.Conditionals; +using NewHorizons.Handlers; +using NewHorizons.Utility.OWML; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace NewHorizons.Components.Conditionals +{ + public class ConditionalsManager : MonoBehaviour + { + public const int MAX_RECURSION = 100; + + List _checks = new(); + int _recursionCount = 0; + bool _avoidRecursionLogSpam = false; + + public void AddCheck(ConditionalCheckInfo check) + { + _checks.Add(check); + } + + public void RemoveCheck(ConditionalCheckInfo check) + { + _checks.Remove(check); + } + + protected void Awake() + { + GlobalMessenger.AddListener("DialogueConditionsReset", CalculateChecks); + GlobalMessenger.AddListener("DialogueConditionChanged", CalculateChecks); + GlobalMessenger.AddListener("NHPersistentConditionChanged", CalculateChecks); + GlobalMessenger.AddListener("ShipLogUpdated", CalculateChecks); + } + + protected void OnDestroy() + { + GlobalMessenger.RemoveListener("DialogueConditionsReset", CalculateChecks); + GlobalMessenger.RemoveListener("DialogueConditionChanged", CalculateChecks); + GlobalMessenger.RemoveListener("NHPersistentConditionChanged", CalculateChecks); + GlobalMessenger.RemoveListener("ShipLogUpdated", CalculateChecks); + } + + protected void Update() + { + _recursionCount = 0; + enabled = false; + } + + void CalculateChecks() + { + if (_recursionCount >= MAX_RECURSION) + { + if (!_avoidRecursionLogSpam) + { + NHLogger.LogError($"Possible infinite loop detected while processing conditional checks. This is likely caused by a mod using conflicting conditional checks that both set and unset the same condition."); + _avoidRecursionLogSpam = true; + } + return; + } + + foreach (var check in _checks) + { + bool checkPassed = ConditionalsHandler.Check(check.check); + if (checkPassed) + { + ConditionalsHandler.ApplyEffects(check.then, checkPassed); + } + } + _recursionCount++; + enabled = true; + } + + // We could theoretically filter checks by conditionName here and only do the checks that matter, but the performance gain is likely not significant enough to be worth the extra complexity + void CalculateChecks(string conditionName, bool conditionState) + { + CalculateChecks(); + } + } +} diff --git a/NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs b/NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs index 6785a8a2..bcc352a9 100644 --- a/NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs +++ b/NewHorizons/Patches/PlayerPatches/PlayerDataPatches.cs @@ -143,5 +143,13 @@ namespace NewHorizons.Patches.PlayerPatches { NewHorizonsData.Save(); } + + [HarmonyPostfix] + [HarmonyPatch(nameof(PlayerData.SetPersistentCondition))] + public static void PlayerData_SetPersistentCondition(string condition, bool state) + { + // Firing off a custom event for the Conditionals system to use. This could've been done with direct calls or a Unity event but it felt cleaner to mirror the vanilla "DialogueConditionChanged" event. + GlobalMessenger.FireEvent("NHPersistentConditionChanged", condition, state); + } } }