using System; using System.Collections; using System.Collections.Generic; using ActionGame; using BepInEx.Bootstrap; using KKAPI.Studio; using UnityEngine; using UnityEngine.SceneManagement; namespace KKAPI.MainGame { /// /// Provides API for interfacing with the main game. It is useful mostly in the actual game, but some /// functions will work outside of it (for example in FreeH). /// public static partial class GameAPI { private static readonly Dictionary _registeredHandlers = new Dictionary(); private static GameObject _functionControllerContainer; /// /// Fired after an H scene is ended, but before it is unloaded. Can be both in the main game and in free h. /// Runs immediately after all objects trigger their events. /// public static event EventHandler EndH; /// /// Fired right after a game save is succesfully loaded. /// Runs immediately after all objects trigger their events. /// public static event EventHandler GameLoad; /// /// Fired right before the game state is saved to file. /// Runs immediately after all objects trigger their events. /// public static event EventHandler GameSave; /// /// Register new functionality that will be added to main game. Offers easy API for custom main game logic. /// All you have to do is create a type that inherits from > /// (don't make instances, the API will make them for you). Warning: The custom controller is immediately /// created when it's registered, but its OnGameLoad method is not called until a game actually loads. /// This might mean that if the registration happens too late you will potentially miss some load events. /// /// Type with your custom logic to add to a character /// Extended data ID used by this behaviour. Set to null if not used. public static void RegisterExtraBehaviour(string extendedDataId) where T : GameCustomFunctionController, new() { if (StudioAPI.InsideStudio) return; var newBehaviour = _functionControllerContainer.AddComponent(); newBehaviour.ExtendedDataId = extendedDataId; _registeredHandlers.Add(newBehaviour, extendedDataId); } /// /// Fired after an H scene is loaded. Can be both in the main game and in free h. /// Runs immediately after all objects trigger their events. /// public static event EventHandler StartH; internal static void Init(bool insideStudio) { if (insideStudio) return; Hooks.SetupHooks(); _functionControllerContainer = new GameObject("GameCustomFunctionController Zoo"); _functionControllerContainer.transform.SetParent(Chainloader.ManagerObject.transform, false); SceneManager.sceneLoaded += (arg0, mode) => { if (arg0.name == "MyRoom" && Manager.Scene.Instance.LoadSceneName != "H") { foreach (var registeredHandler in _registeredHandlers) { try { registeredHandler.Key.OnEnterNightMenu(); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } } }; if (KoikatuAPI.EnableDebugLogging) RegisterExtraBehaviour(null); } private static void OnGameBeingLoaded(string path, string fileName) { var args = new GameSaveLoadEventArgs(path, fileName); foreach (var behaviour in _registeredHandlers) { try { behaviour.Key.OnGameLoad(args); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } try { GameLoad?.Invoke(KoikatuAPI.Instance, args); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } private static void OnGameBeingSaved(string path, string fileName) { var args = new GameSaveLoadEventArgs(path, fileName); foreach (var behaviour in _registeredHandlers) { try { behaviour.Key.OnGameSave(args); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } try { GameSave?.Invoke(KoikatuAPI.Instance, args); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } private static void OnHEnd(HSceneProc proc) { foreach (var behaviour in _registeredHandlers) { try { behaviour.Key.OnEndH(proc, proc.flags.isFreeH); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } try { EndH?.Invoke(KoikatuAPI.Instance, EventArgs.Empty); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } private static IEnumerator OnHStart(HSceneProc proc) { yield return null; foreach (var behaviour in _registeredHandlers) { try { behaviour.Key.OnStartH(proc, proc.flags.isFreeH); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } try { StartH?.Invoke(KoikatuAPI.Instance, EventArgs.Empty); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } private static void OnDayChange(Cycle.Week day) { foreach (var behaviour in _registeredHandlers) { try { behaviour.Key.OnDayChange(day); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } } private static void OnPeriodChange(Cycle.Type period) { foreach (var behaviour in _registeredHandlers) { try { behaviour.Key.OnPeriodChange(period); } catch (Exception e) { KoikatuAPI.Logger.LogError(e); } } } } }