/* * Ghostory has intentional support for Autosplitters built into the game. The data is exposed * through the static class "AutosplitData", which has the following fields: /// /// The current state of the game in human readable format. /// /// Possible values are: /// "Main Menu", "Entering Level", "Playing", "Restarting", "Exiting Level", "Cutscene", "Menu", "Victory", or null. /// public static string gameState = null; /// /// The index of the level the player is in. -1 if not in a level. /// public static int levelIndex = -1; /// /// The in-game time for the current attempt on this level. /// public static float attemptTime = 0f; /// /// The total playtime of this game session. /// public static float totalPlaytime = 0f; /// /// The number of chalices that you have collected. /// public static int chaliceCount = 0; /// /// The total number of jumps in this game session. /// public static int jumpCount = 0; /// /// The total number of keys picked up in this game session. /// public static int keysCount = 0; /// /// The total number of doors opened in this game session. /// public static int doorsCount = 0; /// /// The total number of cages opened in this game session. /// public static int cagesCount = 0; * * If you have an idea for a new speedrun category that can't be autosplit with these values, * jump into Ghostory Steam discussion forum and let the game's developer (me!) know. */ state("Ghostory") {} startup { vars.Unity = Assembly.Load(File.ReadAllBytes(@"Components\UnityASL.bin")).CreateInstance("UnityASL.Unity"); settings.Add("resetOnLevelRestart", false, "Reset on level restart"); settings.Add("keySplit", false, "Split on collected key"); settings.Add("doorSplit", false, "Split on opened door"); settings.Add("cageSplit", false, "Split on opened cage"); } init { vars.Unity.TryOnLoad = (Func)(helper => { var myClass = helper.GetClass("Assembly-CSharp", "AutosplitData"); vars.Unity.MakeString(myClass.Static, myClass["gameState"]).Name = "gameState"; vars.Unity.Make(myClass.Static, myClass["levelIndex"]).Name = "levelIndex"; vars.Unity.Make(myClass.Static, myClass["attemptTime"]).Name = "attemptTime"; vars.Unity.Make(myClass.Static, myClass["totalPlaytime"]).Name = "totalPlaytime"; vars.Unity.Make(myClass.Static, myClass["chaliceCount"]).Name = "chaliceCount"; vars.Unity.Make(myClass.Static, myClass["jumpCount"]).Name = "jumpCount"; vars.Unity.Make(myClass.Static, myClass["keysCount"]).Name = "keysCount"; vars.Unity.Make(myClass.Static, myClass["doorsCount"]).Name = "doorsCount"; vars.Unity.Make(myClass.Static, myClass["cagesCount"]).Name = "cagesCount"; return true; }); vars.Unity.Load(game); } update { if (!vars.Unity.Loaded) return false; vars.Unity.Update(); } start { // Start the timer when you start to control the character. if (vars.Unity["gameState"].Changed && vars.Unity["gameState"].Current == "Playing") { return true; } } split { // 0 is main menu, 1-40 are playable levels, 41 is credits scene. if ( vars.Unity["levelIndex"].Changed && vars.Unity["levelIndex"].Current > 0 && vars.Unity["levelIndex"].Current < 41 ) { return true; } // Hitting the Victory game state is the final split if (vars.Unity["gameState"].Changed && vars.Unity["gameState"].Current == "Victory") { return true; } if (settings["keySplit"]) { if (vars.Unity["keysCount"].Changed) { return true; } } if (settings["doorSplit"]) { if (vars.Unity["doorsCount"].Changed) { return true; } } if (settings["cageSplit"]) { if (vars.Unity["cagesCount"].Changed) { return true; } } } isLoading { // Pause the timer any time when you're not controlling the character. return vars.Unity["gameState"].Current != "Playing"; } reset { // Reset when returned to menu. if (vars.Unity["levelIndex"].Changed && vars.Unity["levelIndex"].Current == 0) { return true; } if (settings["resetOnLevelRestart"]) { // Reset when restarting a level. if (vars.Unity["gameState"].Changed && vars.Unity["gameState"].Current == "Restarting") { return true; } } } exit { vars.Unity.Reset(); } shutdown { vars.Unity.Reset(); }