// Marble Blast Gold Autosplitter // Supports MBG 1.4.1 non-ignited // by thearst3rd and CaptainRektbeard state("marbleblast") { string100 levelFilename : 0x297ABA; } startup { vars.Log = (Action)((output) => print("[Marble Blast Gold ASL] " + output)); vars.ExtractLevelName = (Func)((levelFilename) => levelFilename.Split('/')[4].Split('.')[0]); vars.ExtractLevelType = (Func)((levelFilename) => levelFilename.Split('/')[3]); Dictionary> levelNames = new Dictionary>(); levelNames.Add("beginner", new List() { "movement", "gems", "jumping", "powerjump", "platform", "superspeed", "elevator", "airmove", "copter", "timetrial", "bounce", "gravity", "shock", "backagain", "friction", "bumpers", "ductfan", "mine", "trapdoor", "tornado", "pitfall", "platformparty", "windingroad", "finale" }); levelNames.Add("intermediate", new List() { "jumpjumpjump", "racequalifying", "skatepark", "rampmatrix", "hoops", "goforgreen", "forkinroad", "tritwist", "marbletris", "spaceslide", "skeeball", "playground", "hopskipjump", "highroadlowroad", "halfpipe", "gauntlet", "motomarblecross", "shockdrop", "forkinroad2", "greatdivide", "thewave", "tornado", "racetrack", "upward" }); levelNames.Add("advanced", new List() { "thrillride", "tree", "fan_lift", "leapoffaith", "highway", "steppingstones", "obstacle", "compasspoints", "3foldmaze", "tubetreasure", "slipslide", "skyscraper", "halfpipe2", "a-maze-ing", "blockparty", "trapdoor", "moebius", "greatdivide2", "3foldmaze2", "tothemoon", "aroundtheworld", "willowisp", "twisting", "survival", "plumbing", "siege", "ski", "reloaded", "towermaze", "freefall", "acrobat", "whorl", "mudslide", "pipedreams", "scaffold", "airwalk", "shimmy", "leastresist", "daedalus", "ordeal", "battlements", "pinball", "eyeofthestorm", "dive", "tightrope", "selection", "tango", "icarus", "construction", "pathways", "darwin", "kingofthemountain" }); Func TitleCase = (Func)((input) => input.Substring(0, 1).ToUpper() + input.Substring(1).ToLower()); foreach (string missionType in levelNames.Keys) { settings.Add(missionType, true, TitleCase(missionType) + " Levels"); for (int i=0; i stateStrings = new List() { "Start", "Ready", "set", "Go", "Play", "End" }; // Check all possible offsets for a match with one of the possible state identifiers for (int offset=0x00; offset<0x0FFF; offset++) { IntPtr gameStatePtr; new DeepPointer(game.MainModule.BaseAddress + 0x294A84, offset * 4, 0x0c, 0x00).DerefOffsets(game, out gameStatePtr); string val = game.ReadString(gameStatePtr, 16); if (stateStrings.Contains(val)) { vars.Log("Found $Game::State offset: " + offset.ToString("X")); vars.gameStateOffset = offset; current.gameState = val; break; } } } } else // Otherwise just use the offset to read the string { IntPtr gameStatePtr; new DeepPointer(game.MainModule.BaseAddress+0x294A84, (int)vars.gameStateOffset * 4, 0x0c, 0x00) .DerefOffsets(game, out gameStatePtr); current.gameState = game.ReadString(gameStatePtr, 16); } if (current.gameState != old.gameState) { vars.Log("State Updated: " + current.gameState); } if (current.levelFilename.StartsWith("/data/missions/") && (current.levelFilename != old.levelFilename || vars.firstUpdate)) { vars.Log("Entering level: " + vars.ExtractLevelType(current.levelFilename) + " - " + vars.ExtractLevelName(current.levelFilename)); vars.hasEnteredLevel = true; } vars.firstUpdate = false; } start { if (current.levelFilename.StartsWith("/data/missions/") && !old.levelFilename.StartsWith("/data/missions/")) return true; } split { if (current.gameState == "End" && old.gameState != "End") { string settingName = vars.ExtractLevelType(current.levelFilename) + "_" + vars.ExtractLevelName(current.levelFilename); vars.Log("Finished level: " + settingName); return settings[settingName]; } }