using Cthangover.Core.Bootstrap; using Cthangover.Core.Characters; using Cthangover.Core.Factories; using Cthangover.Core.Factories.Impls; using Cthangover.Core.Mods; using Cthangover.Core.Settings; using Cthangover.Core.Utils; namespace Cthangover.Mods.Characters { /// /// Engine-mod initializer for the characters subsystem. Publishes the /// factories living in this assembly to the kernel contracts /// (, /// , ) /// as soon as the assembly is registered, so core-side consumers — /// CharacterData, inventory and skills UI, dialog avatar lookups — /// resolve templates without referencing a runtime-compiled mod assembly. /// /// Registration happens in (the earliest and /// most frequent initializer callback) rather than on resources-ready: /// CharacterData.AddCharacterToParty is called from other mods' /// OnModResourcesReady (starter party), and initializer callbacks /// are delivered per mod registration, so being first here removes any /// ordering dependency between mods. The factories themselves only /// collect entity data lazily on the first Get, after the mod /// registry is finalized. Registration is guarded and idempotent because /// ModManager.Reload() re-runs OnModLoaded for every mod. /// public class CharactersModInitializer : IModInitializer { private static bool registered; /// Publishes this mod's factories to the kernel registries; safe to call again after a mod reload. public void OnModLoaded(string modId) { if (registered) return; registered = true; CharacterTemplateRegistry.Provider = CharacterFactory.Instance; ActionTemplateRegistry.Provider = ActionCharacterFactory.Instance; AvatarProviderRegistry.Provider = AvatarFactory.Instance; GameLogger.Log("MODS", "CharactersModInitializer: template providers registered (character, action, avatar)"); } /// /// Registers the new-game roster reset owner with AppServices /// (idempotent — duplicates by Id are ignored). Template collection /// stays lazy on first lookup. Persistence needs no setup here: /// is an IModSaveable /// discovered by ModSaveableRegistry automatically. /// public void OnModResourcesReady() { AppServices.Current.RegisterResettable(new CharactersResettable()); } } /// /// New-game state owner of the characters mod: clears the party roster /// and battle set. Today the roster dies implicitly with /// GameData.ResetRuntime (it lives inside RuntimeData), /// which runs before the reset loop, so this reset is a no-op in the /// normal pipeline; it stays correct if the roster ever moves to /// mod-owned static storage (the recruiting path) or if the reset loop /// runs standalone, and makes the characters mod an explicit new-game /// state owner like quests and recruiting. Registered from /// ; /// deduplicates by . /// internal sealed class CharactersResettable : IResettable { /// Resettable key under which AppServices deduplicates registration. public string Id => "characters"; /// Clears the party roster and battle set on "New Game". public void ResetForNewGame() { var characterData = GameData.Instance.Runtime.CharacterData; characterData.Characters.Clear(); characterData.BattleSet.Clear(); } } }