diff --git a/SonicGenerations.asl b/SonicGenerations.asl new file mode 100644 index 0000000..231e606 --- /dev/null +++ b/SonicGenerations.asl @@ -0,0 +1,200 @@ +state("SonicGenerations", "v2") +{ + float StageTime : 0x01A0BE5C, 0x08, 0x184; + float TotalStageTime : 0x01A0BE5C, 0x08, 0x188; + bool stageLoading : 0x01A0BE5C, 0x08, 0x1a8; + + // This address (hitGoal) does the job most of the time (if you die it messes this address up). + ulong hitGoal : 0x01A0BE5C, 0x08, 0xa0; + + byte paused : 0x01A0BE5C, 0x08,0xD0; + string6 stageName : 0x01A0BE5C, 0x08, 0x88, 0x00; + byte stageType : 0x01A0BE5C, 0x08, 0x88, 0x07; + byte inComboSeq : 0x01A0BE5C, 0x08, 0x19c; +} + +startup +{ + // We are currently loading this script. Set up shit here + settings.Add("Real_time", true, "Track Real Time"); + settings.Add("Game_time", false, "Use Game time"); + settings.Add("loading_time", true, "Include loading time in runtime"); + + settings.Add("catagory", true, "Run Catagory"); + settings.CurrentDefaultParent = "catagory"; + settings.Add("any_percent", true); + settings.Add("act1_only", false); + settings.Add("act2_only", false); + + settings.CurrentDefaultParent = null; +} + +init +{ + // We are connected to the process now + if (modules.First().ModuleMemorySize == 0x1CAB000) + version = "v2"; + + //StageID + // pam = Overworld + // ghz = Green Hill + // cpz = Chemical Plant + // ssz = Sky Sanctuary + // sph = Speed Highway + // cte = City Escape + // ssh = Seaside Hill + // csc = Crisis City + // euc = Rooftop Run + // pla = Planet Wisp + + //Bosses + // bde = DeathEgg Robot + // bpc = Perfect Chaos + // bne = Egg Dragoon + // blb = Time Eater + vars.stageDict = new Dictionary(); + vars.stageDict.Add("pam", 1); + vars.stageDict.Add("ghz", 2); + vars.stageDict.Add("cpz", 3); + vars.stageDict.Add("ssz", 4); + vars.stageDict.Add("sph", 5); + vars.stageDict.Add("cte", 6); + vars.stageDict.Add("ssh", 7); + vars.stageDict.Add("csc", 8); + vars.stageDict.Add("euc", 9); + vars.stageDict.Add("pla", 10); + + vars.stageDict.Add("bde", 11); + vars.stageDict.Add("bpc", 12); + vars.stageDict.Add("bne", 13); + vars.stageDict.Add("blb", 14); + + vars.act = 0; + vars.stageID = 0; + vars.stageCode = ""; + vars.inBoss = false; + vars.finalBoss = false; + vars.prevStageEnd = false; + vars.currentStageEnd = false; + + Action DebugOutput = (text) => { + print("[SonicGenerations Autosplitter] "+text); + }; + vars.DebugOutput = DebugOutput; + vars.DebugOutput("test"); +} + +exit +{ + // Connected game closed. Do stuff if needed here + vars.act = 0; + vars.stageID = 0; + vars.stageCode = ""; + vars.inBoss = false; + vars.finalBoss = false; + vars.prevStageEnd = false; + vars.currentStageEnd = false; +} + +start +{ + if(current.stageName != null && current.stageName.Length > 3) + { + vars.act = Convert.ToByte(current.stageName[3].ToString()); + } + + if (settings["any_percent"] == true && current.stageLoading == true && vars.stageID == 1) { + vars.DebugOutput("Any percent timer started"); + return true; + } + else if (settings["act1_only"] == true && vars.act == 1 && current.stageLoading == true) { + vars.DebugOutput("Act1 Timer started"); + return true; + } + else if (settings["act2_only"] == true && vars.act == 2 && current.stageLoading == true) { + vars.DebugOutput("Act2 Timer started"); + return true; + } + return false; +} + +update +{ + // Reset some of the varibles that we are about to set + vars.inBoss = false; + vars.finalBoss = false; + + if(current.stageName != old.stageName) + { + vars.prevStageEnd = vars.currentStageEnd = false; + } + + if(current.stageType == 0x00 && current.stageName != null) // This is always 0 unless a cutscene is running + { + if(current.stageName.Length > 3) + { + vars.act = Convert.ToByte(current.stageName[3].ToString()); + vars.stageCode = "" + current.stageName[0] + current.stageName[1] + current.stageName[2]; + byte tempId = 0; + if(vars.stageDict.TryGetValue(vars.stageCode.ToString(), out tempId)) + { + vars.stageID = tempId; + } + } + else if (current.stageName.Length == 3) + { + vars.inBoss = true; + if(current.stageName == "blb") + { + vars.finalBoss = true; + vars.DebugOutput("In final boss"); + } + + } + } + else + { + vars.DebugOutput("In cutscene"); + } + + //vars.DebugOutput("name: "+current.stageName.ToString()+" id:"+vars.stageID.ToString()+" act:"+vars.act.ToString()+" isloading:"+current.stageLoading.ToString()); + + if(current.hitGoal != old.hitGoal) + { + vars.currentStageEnd = true; + } +} + +split +{ + //TODO See if I can update different segments + //TODO Need to find out how to tell if the stage ended + if(vars.stageID > 1 && vars.currentStageEnd != vars.prevStageEnd) + { + vars.prevStageEnd = vars.currentStageEnd; + if(settings["any_percent"] == true) + { + return true; + } + else if(settings["act1_only"] == true && vars.act == 1) + { + return true; + } + else if(settings["act2_only"] == true && vars.act == 2) + { + return true; + } + } + return false; +} + +isLoading +{ + if(settings["act1_only"] == true && vars.act == 2) + return true; + else if(settings["act2_only"] == true && vars.act == 1) + return true; + + // Only count loading if we set it up like that + return (!settings["loading_time"] && ((vars.stageID == 1) ||current.stageLoading)); +} \ No newline at end of file