state("Bejeweled3") { byte40 completedQuests : 0x487F34, 0xB78, 0x158; byte4 unlockedSecrets : 0x487F34, 0xB78, 0x180; uint questMode : 0x487F34, 0xBD0; int questRelic : 0x487F34, 0xBD0, 0x14C; uint questCaption : 0x487F34, 0xBD0, 0x178; double questCaptionScale : 0x487F34, 0xBD0, 0x178, 0xE0; double questCompletionOpacity : 0x487F34, 0xBD0, 0x308; uint ongoingGame : 0x487F34, 0xBE0; uint ongoingGameMode : 0x487F34, 0xBE0, 0x0; uint gemGrid : 0x487F34, 0xBE0, 0xF4; int score : 0x487F34, 0xBE0, 0xD20; int shownScore : 0x487F34, 0xBE0, 0xD60; bool gameOver : 0x487F34, 0xBE0, 0xD88; bool toBeComplete : 0x487F34, 0xBE0, 0x288C; } startup { refreshRate = 100; settings.Add("secret", false, "Split upon unlocking a Secret Mode"); settings.SetToolTip("secret", "Disables all options below if checked"); settings.Add("quest", true, "Quest autosplit"); settings.Add("quest.50%", false, "50% instead of 100%", "quest"); settings.Add("quest.per_relic", true, "Split upon switching to a new relic", "quest"); settings.SetToolTip("quest.per_relic", "Uncheck to split upon beating a quest (except your last one)"); settings.Add("classic_zen", true, "Classic & Zen autosplit"); settings.Add("classic_zen.point", false, "Score attack", "classic_zen"); settings.SetToolTip("classic_zen.point", "Uncheck to split upon beating a level"); vars.count = new Func<byte[], int>(arr => Array.FindAll(arr, new Predicate<byte>(b => b != 0)).Length); vars.modeChecker = new Func<uint[], Predicate<dynamic>>(modes => new Predicate<dynamic>(state => state.ongoingGame != 0U && state.gemGrid != 0U && modes.Contains((uint)state.ongoingGameMode) ) ); } init { vars.CLASSIC = (uint)(modules.First().BaseAddress + 0x40D644); vars.ZEN = (uint)(modules.First().BaseAddress + 0x40F05C); vars.LIGHTNING = (uint)(modules.First().BaseAddress + 0x40EABC); } start { bool questStarted = old.questMode == 0U && current.questMode != 0U; dynamic started; if (settings["secret"]) { vars.category = "secret"; started = vars.modeChecker(new uint[]{vars.CLASSIC, vars.ZEN, vars.LIGHTNING}); return (questStarted || !started(old) && started(current)) && vars.count(current.unlockedSecrets) == 0; } if (settings["quest"] && questStarted) { vars.category = "quest"; vars.relic = 0; return true; } started = vars.modeChecker(new uint[]{vars.CLASSIC, vars.ZEN}); if (settings["classic_zen"] && !started(old) && started(current) && current.score == 0) { if (settings["classic_zen.point"]) { if (timer.Run.Count == 0) return false; vars.point_split = new List<int>{}; int prev_point = 0; foreach (Segment seg in timer.Run) { int next_point; if (!int.TryParse(seg.Name, out next_point)) return false; if (next_point <= prev_point) return false; vars.point_split.Add(next_point); prev_point = next_point; } } vars.category = "classic_zen"; return true; } return false; } split { if (vars.category == "secret") return vars.count(current.unlockedSecrets) == vars.count(old.unlockedSecrets) + 1; if (vars.category == "quest") { int questCount = vars.count(current.completedQuests); bool captionPopup = old.questCaption != 0U && old.questCaptionScale == 0.0 && current.questCaptionScale > 0.0; if (settings["quest.per_relic"]) { if (current.questRelic > vars.relic) { vars.relic = current.questRelic; return true; } } else { if (questCount != (settings["quest.50%"] ? 19 : 39)) return captionPopup; } if (settings["quest.50%"]) return old.questCompletionOpacity == 0.0 && current.questCompletionOpacity > 0.0; else return questCount == 40 && captionPopup; } if (vars.category == "classic_zen") { if (settings["classic_zen.point"]) return current.shownScore >= vars.point_split[timer.CurrentSplitIndex]; else return old.toBeComplete && !current.toBeComplete; } return false; } reset { if (vars.category == "quest") return old.questMode != 0U && current.questMode == 0U; if (vars.category == "classic_zen") return current.ongoingGame == 0U || current.gameOver; return false; } onReset { vars.category = ""; }