state("ActiveX Flash Player") { } state("Full Series") { } state("All Flash Games") { } state("Trifecta") { } state("Red & Blue Balls") { } startup { vars.gameTime = TimeSpan.FromSeconds(0); vars.debug = false; vars.TimerModel = new TimerModel { CurrentState = timer }; settings.Add("fsAny", false, "Freeze after Levels 12 and 20 in Red Ball 1 and 2 (Full Series Any% Mode)"); settings.Add("gameSplit", false, "Only split after finishing each game"); settings.Add("anyStart", false, "Start the timer upon entering any level (useful for Bonus Levels runs)"); if (timer.CurrentTimingMethod == TimingMethod.RealTime) { var timingMessage = MessageBox.Show ( "This game uses Time without Loads (Game Time) as the main timing method.\n"+ "LiveSplit is currently set to show Real Time (RTA).\n"+ "Would you like to set the timing method to Game Time?", "LiveSplit | Red Ball", MessageBoxButtons.YesNo,MessageBoxIcon.Question ); if (timingMessage == DialogResult.Yes) { timer.CurrentTimingMethod = TimingMethod.GameTime; } } } init { vars.frames = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125DE78, 0x90, 0x3F0, 0x10, 0x0, 0xA0)); vars.freeze = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125DE78, 0x90, 0x3F0, 0x10, 0x0, 0x98)); vars.path = new StringWatcher(new DeepPointer("Flash64_11_5_502_149.ocx", 0x11F42A8), 300); vars.openFrames = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125DE78, 0x1CC)); vars.frames.FailAction = MemoryWatcher.ReadFailAction.SetZeroOrNull; vars.freeze.FailAction = MemoryWatcher.ReadFailAction.SetZeroOrNull; vars.path.FailAction = MemoryWatcher.ReadFailAction.SetZeroOrNull; vars.openFrames.FailAction = MemoryWatcher.ReadFailAction.SetZeroOrNull; vars.path.Update(game); if (vars.path.Current == "") throw new Exception(">>>>> Game Version has not been found yet!"); vars.lastLevelSplit = 0; vars.prevGameTime = TimeSpan.FromSeconds(0); vars.split = false; vars.betweenGames = false; vars.gameSet = false; vars.gameName = ""; } reset { if (!vars.betweenGames && !vars.endLevels.Contains(vars.level.Old) && (vars.level.Current == 0 && !vars.gameName.Contains("Red & Blue Balls")) || (vars.frames.Old > 1 && vars.frames.Current <= 1)) { return true; } } split { if (vars.split) { vars.split = false; return true; } } gameTime { return vars.gameTime; } isLoading { return vars.betweenGames; } onReset { vars.prevGameTime = TimeSpan.FromSeconds(0); vars.gameTime = TimeSpan.FromSeconds(0); vars.lastLevelSplit = 0; vars.betweenGames = false; } update { vars.path.Update(game); vars.openFrames.Update(game); vars.frames.Update(game); vars.freeze.Update(game); if (!vars.gameSet || vars.openFrames.Current < vars.openFrames.Old) { vars.gameSet = false; if (vars.gameName != "" && vars.path.Old == vars.path.Current) { // If a game has previously been set, make sure the path has updated return false; } vars.endLevels = new List<int>(); vars.freezes = new List<int>(); String[] firstStringSplit = vars.path.Current.Split(new string[] { " - Tournament Edition" }, StringSplitOptions.None); String[] secondStringSplit = firstStringSplit[0].Split(new string[] { "\\" }, StringSplitOptions.None); vars.framerate = 30.0; refreshRate = 30; switch (secondStringSplit[secondStringSplit.Length - 1]) { case "Red Ball": vars.startLevels = new List<int>() { 1, 13 }; vars.endLevels = new List<int>() { 12, 17 }; vars.freezes = new List<int>() { 88, 311 }; vars.framerate = 31.0; refreshRate = 31; vars.level = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125FBC0, 0xA0, 0x288, 0x40, 0x0, 0xAC)); break; case "Red Ball 2": vars.startLevels = new List<int>() { 1, 21 }; vars.endLevels = new List<int>() { 20, 25 }; vars.freezes = new List<int>() { 46 }; vars.level = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x1279658, 0x198, 0x50, 0xD0, 0x180, 0xB4)); break; case "Red Ball 3": vars.startLevels = new List<int>() { 1 }; vars.endLevels = new List<int>() { 20 }; vars.freezes = new List<int>() { 46 }; vars.level = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125DE78, 0x90, 0x3F0, 0x18, 0x0, 0xB4)); break; case "Red Ball 4 Vol.1": case "Red Ball 4 Vol.2": case "Red Ball 4 Vol.3": vars.startLevels = new List<int>() { 1 }; vars.endLevels = new List<int>() { 15 }; vars.freezes = new List<int>() { 90 }; vars.level = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125DE78, 0x90, 0x3F0, 0x18, 0x0, 0xA0)); break; case "Red & Blue Balls": vars.startLevels = new List<int>() { 1, 16 }; vars.endLevels = new List<int>() { 15, 20 }; vars.freezes = new List<int>() { 46 }; vars.level = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x1279658, 0x198, 0x50, 0xD0, 0x128, 0xB4)); break; case "Red & Blue Balls 2": case "Red & Blue Balls 3": vars.startLevels = new List<int>() { 1, 26 }; vars.endLevels = new List<int>() { -1 }; vars.freezes = new List<int>() { 40 }; vars.level = new MemoryWatcher<int>(new DeepPointer("Flash64_11_5_502_149.ocx", 0x125DE78, 0x68, 0xA50, 0x700)); break; default: return false; break; } vars.level.FailAction = MemoryWatcher.ReadFailAction.SetZeroOrNull; vars.gameName = secondStringSplit[secondStringSplit.Length - 1]; vars.gameSet = true; if (!vars.betweenGames) { vars.lastLevelSplit = 0; vars.TimerModel.Reset(); vars.prevGameTime = TimeSpan.FromSeconds(0); } } if (!vars.betweenGames && timer.CurrentPhase == TimerPhase.Running) { vars.adjustedFrames = vars.frames.Current; if (vars.lastLevelSplit != vars.level.Current && vars.freeze.Current != 0 && vars.freeze.Old == 0) { vars.lastLevelSplit = vars.level.Current; if (!settings["gameSplit"]) { vars.split = true; } if (vars.freeze.Current < 0) { vars.adjustedFrames = vars.frames.Current - (-1 - vars.freeze.Current); } else if (vars.freezes.Count > 1 && vars.freeze.Current > vars.freezes[0]) { vars.adjustedFrames = vars.frames.Current - (vars.freezes[1] - vars.freeze.Current); } else { vars.adjustedFrames = vars.frames.Current - (vars.freezes[0] - vars.freeze.Current); } if ((settings["fsAny"] && vars.level.Current == vars.endLevels[0]) || (vars.level.Current == vars.endLevels[vars.endLevels.Count - 1]) || (vars.endLevels[0] == -1 && vars.freeze.Current < 0)) { // rabb 2/3 vars.split = true; vars.betweenGames = true; vars.lastLevelSplit = 0; } } vars.gameTime = vars.prevGameTime + TimeSpan.FromSeconds(vars.adjustedFrames / vars.framerate); if (vars.betweenGames) { vars.prevGameTime += TimeSpan.FromSeconds(vars.adjustedFrames / vars.framerate); } } vars.level.Update(game); if ((vars.startLevels.Contains(vars.level.Current) || settings["anyStart"]) && ((vars.frames.Current < vars.frames.Old && vars.frames.Current > 0) || (vars.frames.Current > 1 && vars.frames.Old <= 1))) { // Started timer in level 1 vars.betweenGames = false; vars.TimerModel.Start(); } if (vars.debug) { print("[RB ASL] Current Frames: " + vars.frames.Current + "\n[RB ASL] Current Freeze: " + vars.freeze.Current + "\n[RB ASL] Current Level: " + vars.level.Current + "\n[RB ASL] Game Set: " + vars.gameSet + "\n[RB ASL] Game Name: " + vars.gameName + "\n[RB ASL] Between Games?: " + vars.betweenGames + "\n[RB ASL] Open Frames: " + vars.openFrames.Current + "\n[RB ASL] Previous Game Time: " + vars.prevGameTime.ToString() + "\n[RB ASL] Overall Game Time: " + vars.gameTime.ToString() + "\n[RB ASL] Last Level Split: " + vars.lastLevelSplit + "\n[RB ASL] Frame Rate: " + vars.framerate); } }