using Cthangover.Core.Battle; using Cthangover.Core.Events; using Cthangover.Core.Scenes; using Cthangover.Core.Utils; using Godot; namespace Cthangover.Mods.Rpg { /// /// Starts a battle of the active battle core from the map and brings the /// player back to the same map cell afterwards. It is a thin layer over the /// platform ( + the Battle route): /// /// the return scene is the current map's scene, and the position is /// already in , so the world restores it; /// the backdrop is the map scene's default background (captured by /// the platform from the scene), so a map chooses its battle background in /// scenes/<map>.json; /// an optional win flag becomes the story flag "1" on victory — how a /// map monster disappears after it is beaten (its event's condition). /// /// public static class RpgBattleService { private const string BattleRoute = "Battle"; private const string VictoryResult = "victory"; /// /// Requests the encounter and switches to the battle route on the next /// frame (deferred like switch_scene, so a running dialog finishes /// its current command first). Returns false when there is no scene to come back to. /// public static bool Start(string enemies, string winFlag) { var sceneManager = FindSceneManager(); var returnScene = sceneManager?.CurrentSceneName; if (string.IsNullOrEmpty(returnScene) || string.IsNullOrWhiteSpace(enemies)) { GameLogger.Log("RPG", $"battle not started: scene='{returnScene}', enemies='{enemies}'", LogLevel.Error); return false; } RpgState.Instance.PendingWinFlag = string.IsNullOrWhiteSpace(winFlag) ? null : winFlag.Trim(); BattleService.Init(returnScene, enemies.Replace(" ", string.Empty)); GameLogger.Log("RPG", $"battle '{enemies}' from '{returnScene}' (win flag: {RpgState.Instance.PendingWinFlag ?? "none"})"); Callable.From(() => sceneManager.SwitchScene(BattleRoute)).CallDeferred(); return true; } /// Applies the pending win flag of the battle that just ended. public static void OnBattleEnded(BattleEndedEvent evt) { var flag = RpgState.Instance.PendingWinFlag; RpgState.Instance.PendingWinFlag = null; if (flag != null && evt?.Result == VictoryResult) ScenarioCondition.SetFlag(flag, "1"); } private static SceneManager FindSceneManager() { var tree = Godot.Engine.GetMainLoop() as SceneTree; return tree?.Root?.GetNodeOrNull("SceneManager"); } } }