state("SkinFreak") { } startup { // Load asl-help binary and instantiate it - will inject code into the asl in the background Assembly.Load(File.ReadAllBytes("Components/asl-help")).CreateInstance("Unity"); vars.Helper.LoadSceneManager = true; vars.Helper.GameName = "SkinFreak"; vars.Helper.AlertLoadless(); #region TextComponent //Dictionary to cache created/reused layout components by their left-hand label (Text1) vars.lcCache = new Dictionary(); //Function to set (or update) a text component vars.SetText = (Action)((text1, text2) => { const string FileName = "LiveSplit.Text.dll"; LiveSplit.UI.Components.ILayoutComponent lc; //Try to find an existing layout component with matching Text1 (label) if (!vars.lcCache.TryGetValue(text1, out lc)) { lc = timer.Layout.LayoutComponents.Reverse().Cast() .FirstOrDefault(llc => llc.Path.EndsWith(FileName) && llc.Component.Settings.Text1 == text1) ?? LiveSplit.UI.Components.ComponentManager.LoadLayoutComponent(FileName, timer); //Cache it for later reference vars.lcCache.Add(text1, lc); } //If it hasn't been added to the layout yet, add it if (!timer.Layout.LayoutComponents.Contains(lc)) timer.Layout.LayoutComponents.Add(lc); //Set the label (Text1) and value (Text2) of the text component dynamic tc = lc.Component; tc.Settings.Text1 = text1; tc.Settings.Text2 = text2.ToString(); }); //Function to remove a single text component by its label vars.RemoveText = (Action)(text1 => { LiveSplit.UI.Components.ILayoutComponent lc; //If it's cached, remove it from the layout and the cache if (vars.lcCache.TryGetValue(text1, out lc)) { timer.Layout.LayoutComponents.Remove(lc); vars.lcCache.Remove(text1); } }); //Function to remove all text components that were added via this script vars.RemoveAllTexts = (Action)(() => { //Remove each one from the layout foreach (var lc in vars.lcCache.Values) timer.Layout.LayoutComponents.Remove(lc); //Clear the cache vars.lcCache.Clear(); }); #endregion #region setting creation dynamic[,] _settings = { { "LevelSplits", true, "Level Splits", null }, { "01 - Office", true, "01 - Office", "LevelSplits" }, { "02 - BOSS", true, "02 - Boss", "LevelSplits" }, { "UnityInfo", true, "Unity Scene Info", null }, { "LScene Name: ", false, "Name of Loading Scene", "UnityInfo" }, { "AScene Name: ", true, "Name of Active Scene", "UnityInfo" }, { "DebugInfo", false, "Debug Info", null }, { "placeholder", false, "placeholder", "DebugInfo" }, }; vars.Helper.Settings.Create(_settings); #endregion } init { vars.SceneLoading = ""; //Enable if having scene print issues - a custom function defined in init, the `scene` is the scene's address (e.g. vars.Helper.Scenes.Active.Address) vars.ReadSceneName = (Func)(scene => { string name = vars.Helper.ReadString(256, ReadStringType.UTF8, scene + 0x38); return name == "" ? null : name; }); // This is where we will load custom properties from the code vars.Helper.TryLoad = (Func)(mono => { //vars.Helper["placeholder"] = mono.Make("PauseManager", "GameIsPaused"); return true; }); //Clears errors when scene and other variables are null, will get updated once they get detected current.placeholder = 0; current.Scene = ""; current.activeScene = ""; current.loadingScene = ""; current.loading = false; //Helper function that sets or removes text depending on whether the setting is enabled - only works in `init` or later because `startup` cannot read setting values vars.SetTextIfEnabled = (Action)((text1, text2) => { if (settings[text1]) //If the matching setting is checked vars.SetText(text1, text2); //Show the text else vars.RemoveText(text1); //Otherwise, remove it }); } update { vars.Helper.Update(); vars.Helper.MapPointers(); //Get the current active scene's name and set it to `current.activeScene` - sometimes, it is null, so fallback to old value current.activeScene = vars.Helper.Scenes.Active.Name ?? current.activeScene; //Usually the scene that's loading, a bit jank in this version of asl-help current.loadingScene = vars.Helper.Scenes.Loaded[0].Name ?? current.loadingScene; if(!String.IsNullOrWhiteSpace(vars.Helper.Scenes.Active.Name)) current.activeScene = vars.Helper.Scenes.Active.Name; if(!String.IsNullOrWhiteSpace(vars.Helper.Scenes.Loaded[0].Name)) current.loadingScene = vars.Helper.Scenes.Loaded[0].Name; //Log changes to properties if(old.activeScene != current.activeScene) {vars.Log("activeScene: " + old.activeScene + " -> " + current.activeScene);} if(old.loadingScene != current.loadingScene) {vars.Log("loadingScene: " + old.loadingScene + " -> " + current.loadingScene);} //More text component stuff - checking for setting and then generating the text. No need for .ToString since we do that previously vars.SetTextIfEnabled("placeholder",current.placeholder); vars.SetTextIfEnabled("LScene Name: ",current.loadingScene); vars.SetTextIfEnabled("AScene Name: ",current.activeScene); //vars.Log(current.activeScene); } start { return old.activeScene == "00 - Main Menu" && current.activeScene != "00 - Main Menu"; } isLoading { return current.loadingScene != current.activeScene; }