// timeFromNewGame : IGT from New Game // * Equals 0 when hitting New Game // * Stops when dying // * Steps back after dying //state("BGE","UPlay") //{ // float timeFromNewGame : 0x00733EAC, 0x2A8; // http://y.zxq.co/uvamhp.png from Piorrro33 // float time : 0x002CEBFD, 0x0; // same as Steam_NoPatch // string50 map : 0x00730CE4, 0x1D4; //} // //state("BGE","Steam_NoPatch") //{ // float timeFromNewGame : 0x007880C8, 0x0; // float time : 0x002CEBFD, 0x0; // string50 map : 0x00789DA8; //} state("BGE","unknown") { // Default state } state("BGE","CD_Polish") { float timeFromNewGame : 0x00784A48, 0x0; //float timeSinceBoot : 0x007912A0; // timeSinceBoot string50 map : 0x00790FE8; int isLoading : 0x00790F4C; int isCutscenePlayingInBossRoom : 0x007851E0, 0x0; } state("BGE","GOG") { float timeFromNewGame : 0x0077D808, 0x0; //float timeSinceBoot : 0x0078A05C; // timeSinceBoot, -0x7244 w/ Polish, all others are -0x7240 string50 map : 0x00789DA8; int isLoading : 0x00789D0C; int isCutscenePlayingInBossRoom : 0x0077DFA0, 0x0; } startup { refreshRate = 60; //----------------------------------------------// settings.Add("any%", true, "Any%"); settings.Add("other", false, "Other"); settings.CurrentDefaultParent = "any%"; settings.Add("intro", false, "Intro"); settings.Add("lighthouse", true, "Lighthouse"); settings.Add("early_beluga", true, "Early Beluga"); settings.Add("pterolimax", false, "Pterolimax (Black Isle Boss)"); settings.Add("black_isle", true, "Black Isle (after clearing the area)"); settings.Add("volcano_treasure", true, "Volcano's Treasure"); settings.Add("spirit_reaper", true, "Spirit Reaper (after exiting the room)"); settings.Add("nutripils_factory", true, "Nutripils Factory"); settings.Add("to_the_moon", true, "To The Moon"); settings.Add("moon_hacking", false, "Moon Transmitter Hacking"); settings.Add("alpha_spider", true, "Triple Elevator"); settings.Add("domz_priest", true, "DomZ Priest"); settings.CurrentDefaultParent = "other"; settings.Add("evidence_1", false, "Slaughterhouses Evidence 1 (horizontal elevator)"); settings.Add("evidence_2", false, "Slaughterhouses Evidence 2 (horizontal elevator)"); settings.Add("evidence_3", false, "Slaughterhouses Evidence 3"); settings.Add("looter_1", false, "Looter's Cavern 1"); settings.Add("looter_2", false, "Looter's Cavern 2"); settings.Add("looter_3", false, "Looter's Cavern 3"); settings.Add("looter_4", false, "Looter's Cavern 4"); settings.Add("race_1", false, "Race 1"); settings.Add("race_2", false, "Race 2"); settings.Add("race_3", false, "Race 3"); settings.Add("race_4", false, "Race 4"); settings.Add("races_1_2", false, "Races 1 & 2"); settings.Add("races_3_4", false, "Races 3 & 4"); settings.Add("square_key_quarters", false, "Alpha Section Und. Quarters (Square Key)"); settings.Add("vorax_lair", false, "Vorax's Lair"); //----------------------------------------------// vars.GetSplitList = (Func<Dictionary<string, KeyValuePair<string, string>>>)(() => { return new Dictionary<string, KeyValuePair<string, string>> { {"intro", new KeyValuePair<string, string>("00_03_dehors_maison_Intro", "00_03_dehors_maison_Waf")}, {"lighthouse", new KeyValuePair<string, string>("00_01_home_sas_hangar", "04_00_vaisseau_hyllis_planete")}, {"early_beluga", new KeyValuePair<string, string>("06_12_animaux_garage", "04_00_vaisseau_hyllis_planete")}, {"pterolimax", new KeyValuePair<string, string>("05_02_ilot_boss", "05_00_ilot_sas_accueil")}, {"black_isle", new KeyValuePair<string, string>("05_00_ilot_sas_accueil", "04_00_vaisseau_hyllis_planete")}, {"volcano_treasure", new KeyValuePair<string, string>("11_13_Combat_06", "04_00_vaisseau_hyllis_planete")}, {"spirit_reaper", new KeyValuePair<string, string>("01_01_entrepot_ascenseur_central", "01_02_entrepot_salle_fusibles")}, {"nutripils_factory", new KeyValuePair<string, string>("01_00_entrepot_sas_entree", "04_00_vaisseau_hyllis_planete")}, {"to_the_moon", new KeyValuePair<string, string>("04_00_vaisseau_hyllis_planete", "04_01_vaisseau_hyllis_espace")}, {"moon_hacking", new KeyValuePair<string, string>("08_03_satellite_emetteur", "06_00_Animaux_quartier_pietons_revolution")}, {"alpha_spider", new KeyValuePair<string, string>("04_02_vaisseau_lune", "09_01_nazh_boss")}, {"domz_priest", new KeyValuePair<string, string>("09_01_nazh_boss", "09_01_nazh_boss_cine_finale")}, // the split is performed before map transition {"evidence_1", new KeyValuePair<string, string>("03_07_egouts_abattoir_interieur", "03_05_egouts_cyclope_derriere")}, {"evidence_2", new KeyValuePair<string, string>("03_07_egouts_abattoir_interieur", "03_15_egouts_stealth_02")}, {"evidence_3", new KeyValuePair<string, string>("03_07_egouts_abattoir_interieur", "03_14_egouts_stealth_01")}, {"looter_1", new KeyValuePair<string, string>("11_00_vieux_fou_01", "04_00_vaisseau_hyllis_planete")}, {"looter_2", new KeyValuePair<string, string>("11_01_vieux_fou_02", "04_00_vaisseau_hyllis_planete")}, {"looter_3", new KeyValuePair<string, string>("11_02_vieux_fou_03", "04_00_vaisseau_hyllis_planete")}, {"looter_4", new KeyValuePair<string, string>("11_03_vieux_fou_04", "04_00_vaisseau_hyllis_planete")}, {"race_2", new KeyValuePair<string, string>("07_02_course_02", "07_00_course_00")}, {"race_4", new KeyValuePair<string, string>("07_04_course_04", "07_03_course_03")}, {"races_1_2", new KeyValuePair<string, string>("07_00_course_00", "06_00_Animaux_Canaux")}, {"races_3_4", new KeyValuePair<string, string>("", "04_00_vaisseau_hyllis_planete")}, //{"slaughterhouses_entrance", new KeyValuePair<string, string>("", "04_00_vaisseau_hyllis_planete")}, {"square_key_quarters", new KeyValuePair<string, string>("11_10_Combat_03", "04_00_vaisseau_hyllis_planete")}, {"vorax_lair", new KeyValuePair<string, string>("11_08_Combat_01", "04_00_vaisseau_hyllis_planete")}, }; }); vars.startOffset = 0f; // Depends how the player restarts the game vars.totalLoadTime = 0f; // How much loading we went through vars.lastLoadStartTimestamp = null; // Timestamp when last loading started vars.finalBossHitTimestamp = null; // Timestamp when last boss hit cutscene triggers vars.mammago = 0; // Trick variable for Mammago Garage split vars.finalBossCutscenesLeft = 0; // Counts the numbers of cutscenes left before the boss is beaten vars.end_delay = 0f; // How long to wait after boss cutscene starts in order to stop the timer vars.splits = null; // List of splits vars.Init = (Action<string>)((string oldMap) => { // Sets a LiveSplit offset depending on where New Game is triggered from if(oldMap.Contains("_main_logo")) vars.startOffset = 0.583; //0.533; else if(oldMap.Contains("dehors_maison_Intro")) vars.startOffset = 0.166; else vars.startOffset = 0.333; timer.Run.Offset = TimeSpan.FromSeconds(vars.startOffset); vars.totalLoadTime = 0f; vars.lastLoadStartTimestamp = null; vars.finalBossHitTimestamp = null; vars.mammago = 1; vars.finalBossCutscenesLeft = 3; vars.end_delay = 3.076; vars.splits = vars.GetSplitList(); }); vars.IsStart = (Func<float, double, string, bool>)((float refTime, double fps, string refMap) => { return refTime < 4f/fps && refMap.Contains("dehors_maison_Intro"); }); } init { print("[BGE/init] ModuleMemorySize: "+modules.First().ModuleMemorySize); switch(modules.First().ModuleMemorySize){ //case 9457664 : version = "UPlay"; // break; //case 9768960 : version = "Steam_NoPatch"; // break; case 9760768 : version = "GOG"; break; //case 10006528: version = "Steam"; // break; case 9850880 : version = "CD_Polish"; break; default : version = "unknown"; break; } } update { if(version == "unknown") return false; // Don't update on main menu if a run hasn't started. if(timer.CurrentTime.RealTime.Value.TotalSeconds < 1f) { // User is in introduction/main menus switch((string)current.map){ case "" : case "_main_fix": case "_main_logo": case "_main_credits": case "logo": case "_SFX_light&smoke": return false; default : break; } } // Handling loading time if(current.isLoading == 1 && vars.lastLoadStartTimestamp == null) vars.lastLoadStartTimestamp = timer.CurrentTime.RealTime.Value; if(current.isLoading == 0 && vars.lastLoadStartTimestamp != null) { vars.totalLoadTime += (timer.CurrentTime.RealTime.Value - vars.lastLoadStartTimestamp).TotalSeconds; vars.lastLoadStartTimestamp = null; print("[BGE/update] totalLoadTime: "+vars.totalLoadTime); } //print("[BGE/update] "+current.time+" "+old.time+" "+refreshRate+" "+vars.totalLoadTime); return true; } start { //print("[BGE/start] "+current.timeFromNewGame+" "+(string)current.map);; if (vars.IsStart(current.timeFromNewGame, refreshRate, (string)current.map)) { vars.Init((string)old.map); print("[BGE/start] Offset: "+timer.Run.Offset); return true; } return false; } isLoading { // No gametime interpolation return true; } gameTime { var time = (current.isLoading == 1) ? vars.lastLoadStartTimestamp.TotalSeconds : timer.CurrentTime.RealTime.Value.TotalSeconds; return TimeSpan.FromSeconds(time - vars.startOffset - vars.totalLoadTime); } split { if(vars.splits == null) return false; foreach(var _split in vars.splits) { if(settings[_split.Key]) { var _pair = _split.Value; if(((string)old.map).Contains(_pair.Key) && ((string)current.map).Contains(_pair.Value)) { if(_split.Key == "early_beluga" && vars.mammago > 0) --vars.mammago; else if(_split.Key == "domz_priest") { /* don't split, delay handled below */ } else // Classic split on map transition { vars.splits.Remove(_split.Key); return true; } } if(_split.Key == "domz_priest" && ((string)current.map).Contains("09_01_nazh_boss")) { //print("[BGE/split] "+vars.finalBossCutscenesLeft); // Cutscene triggered ? if(current.isCutscenePlayingInBossRoom - old.isCutscenePlayingInBossRoom == 1) --vars.finalBossCutscenesLeft; // Has died after mind control ? if(vars.finalBossCutscenesLeft == 1 && current.timeFromNewGame < old.timeFromNewGame) ++vars.finalBossCutscenesLeft; // Final cutscene ? if(vars.finalBossCutscenesLeft <= 0) { if(vars.finalBossHitTimestamp == null) vars.finalBossHitTimestamp = timer.CurrentTime.RealTime.Value; // Waiting for final hit //print("[BGE/split] "+(timer.CurrentTime.RealTime.Value.TotalSeconds - vars.finalBossHitTimestamp.TotalSeconds)); if((timer.CurrentTime.RealTime.Value.TotalSeconds - vars.finalBossHitTimestamp.TotalSeconds) >= vars.end_delay) { vars.splits.Remove(_split.Key); return true; } } } } } } reset { //print("[BGE/reset] "+current.timeFromNewGame+" "+timer.CurrentTime.RealTime.Value.TotalSeconds+" "+(string)current.map); if(timer.CurrentTime.RealTime.Value.TotalSeconds > 5f && vars.IsStart(current.timeFromNewGame, refreshRate, (string)current.map)) { vars.Init((string)old.map); print("[BGE/start] Offset: "+timer.Run.Offset); return true; } return false; } exit { } shutdown { }