//SW: KotOR II Autosplitter - Release 3 - Test (1 May 2024) //Full Configuration //credits to: Xer0, Glasnonck, the_kovic, RedMage08, Lane_d // Addresses for Steam version with Aspyr update state("swkotor2", "Steam") { string6 area : "swkotor2.exe", 0x0061B4A4, 0x4, 0x4, 0x2FC, 0x5; int isLoading : "swkotor2.exe", 0x0061B4A4, 0x4, 0x4, 0x278, 0xCC; int isActiveWindow : "swkotor2.exe", 0x0061B4E0; int isNotAMG : "swkotor2.exe", 0x006309D0; int trayaBattleState : "swkotor2.exe", 0x0061B4A4, 0x8, 0x4, 0x1e136; } // Addresses for GOG version with Aspyr update state("swkotor2", "GOG") { string6 area : "swkotor2.exe", 0x00611C04, 0x4, 0x4, 0x2FC, 0x5; int isLoading : "swkotor2.exe", 0x00611C04, 0x4, 0x4, 0x278, 0xCC; int isActiveWindow : "swkotor2.exe", 0x00611C40; int isNotAMG : "swkotor2.exe", 0x00632BA0; int trayaBattleState : "swkotor2.exe", 0x00611C04, 0x8, 0x4, 0x1e136; } startup { // EBON HAWK settings.Add("ebo_main", false, "Ebon Hawk Splits"); settings.Add("001EBO", false, "001EBO - Interior (Tutorial)", "ebo_main"); settings.Add("001EBO_unlim", false, "Unlimited Splits", "001EBO"); settings.Add("002EBO", false, "002EBO - Exterior Hull (Tutorial)", "ebo_main"); settings.Add("002EBO_unlim", false, "Unlimited Splits", "002EBO"); settings.Add("003EBO", false, "003EBO - Interior(Regular Ebon Hawk)", "ebo_main"); settings.Add("003EBO_unlim", false, "Unlimited Splits", "003EBO"); settings.Add("004EBO", false, "004EBO - Interior (Red Eclipse Ambush)", "ebo_main"); settings.Add("004EBO_unlim", false, "Unlimited Splits", "004EBO"); settings.Add("005EBO", false, "005EBO - Interior (Peragus Escape after Turret Minigame)", "ebo_main"); settings.Add("005EBO_unlim", false, "Unlimited Splits", "005EBO"); settings.Add("006EBO", false, "006EBO - Interior (Post Jedi Enclave)", "ebo_main"); settings.Add("006EBO_unlim", false, "Unlimited Splits", "006EBO"); settings.Add("007EBO", false, "007EBO - Interior (Post Goto's Yacht)", "ebo_main"); settings.Add("007EBO_unlim", false, "Unlimited Splits", "007EBO"); // PERAGUS settings.Add("per_main", false, "Peragus Splits"); settings.Add("101PER", false, "101PER - Administration Level", "per_main"); settings.Add("101PER_unlim", false, "Unlimited Splits", "101PER"); settings.Add("102PER", false, "102PER - Mining Tunnels", "per_main"); settings.Add("102PER_unlim", false, "Unlimited Splits", "102PER"); settings.Add("103PER", false, "103PER - Fuel Depot", "per_main"); settings.Add("103PER_unlim", false, "Unlimited Splits", "103PER"); settings.Add("104PER", false, "104PER - Asteroid Exterior", "per_main"); settings.Add("104PER_unlim", false, "Unlimited Splits", "104PER"); settings.Add("105PER", false, "105PER - Dormitories", "per_main"); settings.Add("105PER_unlim", false, "Unlimited Splits", "105PER"); settings.Add("106PER", false, "106PER - Hangar Bay", "per_main"); settings.Add("106PER_unlim", false, "Unlimited Splits", "106PER"); settings.Add("107PER", false, "107PER - Turret Minigame/Escape Sequence", "per_main"); settings.Add("107PER_unlim", false, "Unlimited Splits", "107PER"); // HARBINGER settings.Add("har_main", false, "Harbinger Splits"); settings.Add("151HAR", false, "151HAR - Command Deck", "har_main"); settings.Add("151HAR_unlim", false, "Unlimited Splits", "151HAR"); settings.Add("152HAR", false, "152HAR - Crew Quarters", "har_main"); settings.Add("152HAR_unlim", false, "Unlimited Splits", "152HAR"); settings.Add("153HAR", false, "153HAR - Engine Deck", "har_main"); settings.Add("153HAR_unlim", false, "Unlimited Splits", "153HAR"); settings.Add("154HAR", false, "154HAR - Command Deck Cutscene", "har_main"); settings.Add("154HAR_unlim", false, "Unlimited Splits", "154HAR"); // TELOS settings.Add("tel_main", false, "Telos Splits"); settings.Add("201TEL", false, "201TEL - Citadel Station Docking Module", "tel_main"); settings.Add("201TEL_unlim", false, "Unlimited Splits", "201TEL"); settings.Add("202TEL", false, "202TEL - Citadel Station Entertainment Module 081", "tel_main"); settings.Add("202TEL_unlim", false, "Unlimited Splits", "202TEL"); settings.Add("203TEL", false, "203TEL - Citadel Station Residential 082 East", "tel_main"); settings.Add("203TEL_unlim", false, "Unlimited Splits", "203TEL"); settings.Add("204TEL", false, "204TEL - Citadel Station Residential 082 West", "tel_main"); settings.Add("204TEL_unlim", false, "Unlimited Splits", "204TEL"); settings.Add("205TEL", false, "205TEL - Citadel Station Residential 082 West - Carth Cutscene to Malachor V", "tel_main"); settings.Add("205TEL_unlim", false, "Unlimited Splits", "205TEL"); settings.Add("207TEL", false, "207TEL - Citadel Station Cantina", "tel_main"); settings.Add("207TEL_unlim", false, "Unlimited Splits", "207TEL"); settings.Add("208TEL", false, "208TEL - Citadel Station Bumani Exchange Corporation", "tel_main"); settings.Add("208TEL_unlim", false, "Unlimited Splits", "208TEL"); settings.Add("209TEL", false, "209TEL - Citadel Station Czerka Offices", "tel_main"); settings.Add("209TEL_unlim", false, "Unlimited Splits", "209TEL"); settings.Add("211TEL", false, "211TEL - Citadel Station Swoop Track", "tel_main"); settings.Add("211TEL_unlim", false, "Unlimited Splits", "211TEL"); settings.Add("220TEL", false, "220TEL - Citadel Station Residental East - Sith Assault", "tel_main"); settings.Add("220TEL_unlim", false, "Unlimited Splits", "220TEL"); settings.Add("221TEL", false, "221TEL - Citadel Station Residental West - Sith Assault (cutscene w/ Grenn)99", "tel_main"); settings.Add("221TEL_unlim", false, "Unlimited Splits", "221TEL"); settings.Add("222TEL", false, "222TEL - Citadel Station Entertainment Module 081 - Sith Assault", "tel_main"); settings.Add("222TEL_unlim", false, "Unlimited Splits", "222TEL"); settings.Add("231TEL", false, "231TEL - Restoration Zone", "tel_main"); settings.Add("231TEL_unlim", false, "Unlimited Splits", "231TEL"); settings.Add("232TEL", false, "232TEL - Underground Base", "tel_main"); settings.Add("232TEL_unlim", false, "Unlimited Splits", "232TEL"); settings.Add("233TEL", false, "233TEL - Czerka Site", "tel_main"); settings.Add("233TEL_unlim", false, "Unlimited Splits", "233TEL"); settings.Add("261TEL", false, "261TEL - Polar Plateau", "tel_main"); settings.Add("261TEL_unlim", false, "Unlimited Splits", "261TEL"); settings.Add("262TEL", false, "262TEL - Secret Academy", "tel_main"); settings.Add("262TEL_unlim", false, "Unlimited Splits", "262TEL"); settings.Add("950COR", false, "950COR - Ebon Hawk & Coruscant Cutscene After Leaving Telos", "tel_main"); settings.Add("950COR_unlim", false, "Unlimited Splits", "950COR"); // NAR SHADDAA settings.Add("nar_main", false, "Nar Shaddaa Splits"); settings.Add("301NAR", false, "301NAR - Refugee Landing Pad", "nar_main"); settings.Add("301NAR_unlim", false, "Unlimited Splits", "301NAR"); settings.Add("302NAR", false, "302NAR - Refugee Quad", "nar_main"); settings.Add("302NAR_unlim", false, "Unlimited Splits", "302NAR"); settings.Add("303NAR", false, "303NAR - Docks", "nar_main"); settings.Add("303NAR_unlim", false, "Unlimited Splits", "303NAR"); settings.Add("304NAR", false, "304NAR - Jek'Jekk Tarr", "nar_main"); settings.Add("304NAR_unlim", false, "Unlimited Splits", "304NAR"); settings.Add("305NAR", false, "305NAR - Jekk'Jekk Tunnels", "nar_main"); settings.Add("305NAR_unlim", false, "Unlimited Splits", "305NAR"); settings.Add("306NAR", false, "306NAR - Entertainment Promenade", "nar_main"); settings.Add("306NAR_unlim", false, "Unlimited Splits", "306NAR"); settings.Add("351NAR", false, "351NAR - Goto's Yacht", "nar_main"); settings.Add("351NAR_unlim", false, "Unlimited Splits", "351NAR"); settings.Add("352NAR", false, "352NAR - Goto's Yacht (cutscene)", "nar_main"); settings.Add("352NAR_unlim", false, "Unlimited Splits", "352NAR"); settings.Add("371NAR", false, "371NAR - Swoop Track", "nar_main"); settings.Add("371NAR_unlim", false, "Unlimited Splits", "371NAR"); // DXUN settings.Add("dxn_main", false, "Dxun Splits"); settings.Add("401DXN", false, "401DXN - Jungle Landing", "dxn_main"); settings.Add("401DXN_unlim", false, "Unlimited Splits", "401DXN"); settings.Add("402DXN", false, "402DXN - Jungle", "dxn_main"); settings.Add("402DXN_unlim", false, "Unlimited Splits", "402DXN"); settings.Add("403DXN", false, "403DXN - Mandalorian Camp", "dxn_main"); settings.Add("403DXN_unlim", false, "Unlimited Splits", "403DXN"); settings.Add("404DXN", false, "404DXN - Mandalorian Cache", "dxn_main"); settings.Add("404DXN_unlim", false, "Unlimited Splits", "404DXN"); settings.Add("410DXN", false, "410DXN - Jungle Tomb", "dxn_main"); settings.Add("410DXN_unlim", false, "Unlimited Splits", "410DXN"); settings.Add("411DXN", false, "411DXN - Sith Tomb", "dxn_main"); settings.Add("411DXN_unlim", false, "Unlimited Splits", "411DXN"); settings.Add("421DXN", false, "421DXN - Turret Minigame", "dxn_main"); settings.Add("421DXN_unlim", false, "Unlimited Splits", "421DXN"); // ONDERON settings.Add("ond_main", false, "Onderon Splits"); settings.Add("501OND", false, "501OND - Iziz Spaceport", "ond_main"); settings.Add("501OND_unlim", false, "Unlimited Splits", "501OND"); settings.Add("502OND", false, "502OND - Merchant Quarter", "ond_main"); settings.Add("502OND_unlim", false, "Unlimited Splits", "502OND"); settings.Add("503OND", false, "503OND - Iziz Cantina", "ond_main"); settings.Add("503OND_unlim", false, "Unlimited Splits", "503OND"); settings.Add("504OND", false, "504OND - Sky Ramp", "ond_main"); settings.Add("504OND_unlim", false, "Unlimited Splits", "504OND"); settings.Add("505OND", false, "505OND - Turret", "ond_main"); settings.Add("505OND_unlim", false, "Unlimited Splits", "505OND"); settings.Add("506OND", false, "506OND - Royal Palace", "ond_main"); settings.Add("506OND_unlim", false, "Unlimited Splits", "506OND"); settings.Add("510OND", false, "510OND - Swoop Race Track", "ond_main"); settings.Add("510OND_unlim", false, "Unlimited Splits", "510OND"); settings.Add("511OND", false, "511OND - Merchant Quarter", "ond_main"); settings.Add("511OND_unlim", false, "Unlimited Splits", "511OND"); settings.Add("512OND", false, "512OND - Iziz Western Square", "ond_main"); settings.Add("512OND_unlim", false, "Unlimited Splits", "512OND"); // DANTOOINE settings.Add("dan_main", false, "Dantooine Splits"); settings.Add("601DAN", false, "601DAN - Khoonda", "dan_main"); settings.Add("601DAN_unlim", false, "Unlimited Splits", "601DAN"); settings.Add("602DAN", false, "602DAN - Khoonda Plains", "dan_main"); settings.Add("602DAN_unlim", false, "Unlimited Splits", "602DAN"); settings.Add("603DAN", false, "603DAN - Movie Terminal on Khoonda Plains", "dan_main"); settings.Add("603DAN_unlim", false, "Unlimited Splits", "603DAN"); settings.Add("604DAN", false, "604DAN - Crystal Cave", "dan_main"); settings.Add("604DAN_unlim", false, "Unlimited Splits", "604DAN"); settings.Add("605DAN", false, "605DAN - Enclave Courtyard", "dan_main"); settings.Add("605DAN_unlim", false, "Unlimited Splits", "605DAN"); settings.Add("610DAN", false, "610DAN - Enclave Sublevel", "dan_main"); settings.Add("610DAN_unlim", false, "Unlimited Splits", "610DAN"); settings.Add("650DAN", false, "650DAN - Rebuilt Jedi Enclave", "dan_main"); settings.Add("650DAN_unlim", false, "Unlimited Splits", "650DAN"); // KORRIBAN settings.Add("kor_main", false, "Korriban Splits"); settings.Add("701KOR", false, "701KOR - Valley of the Dark Lords", "kor_main"); settings.Add("701KOR_unlim", false, "Unlimited Splits", "701KOR"); settings.Add("702KOR", false, "702KOR - Sith Academy", "kor_main"); settings.Add("702KOR_unlim", false, "Unlimited Splits", "702KOR"); settings.Add("710KOR", false, "710KOR - Shyrack Cave", "kor_main"); settings.Add("710KOR_unlim", false, "Unlimited Splits", "710KOR"); settings.Add("711KOR", false, "711KOR - Secret Tomb", "kor_main"); settings.Add("711KOR_unlim", false, "Unlimited Splits", "711KOR"); // RAVAGER settings.Add("rav_main", false, "Ravager Splits"); settings.Add("851NIH", false, "851NIH - Command Deck", "rav_main"); settings.Add("851NIH_unlim", false, "Unlimited Splits", "851NIH"); settings.Add("852NIH", false, "852NIH - Bridge", "rav_main"); settings.Add("852NIH_unlim", false, "Unlimited Splits", "852NIH"); settings.Add("853NIH", false, "853NIH - Visas-Nihilus Cutscene", "rav_main"); settings.Add("853NIH_unlim", false, "Unlimited Splits", "853NIH"); // MALACHOR V settings.Add("mal_main", false, "Malachor V Splits"); settings.Add("901MAL", false, "901MAL - Surface", "mal_main"); settings.Add("901MAL_unlim", false, "Unlimited Splits", "901MAL"); settings.Add("902MAL", false, "902MAL - Depths", "mal_main"); settings.Add("902MAL_unlim", false, "Unlimited Splits", "902MAL"); settings.Add("903MAL", false, "903MAL - Trayus Academy", "mal_main"); settings.Add("903MAL_unlim", false, "Unlimited Splits", "903MAL"); settings.Add("904MAL", false, "904MAL - Trayus Core (Final Module)", "mal_main"); settings.Add("904MAL_unlim", false, "Unlimited Splits", "904MAL"); settings.Add("905MAL", false, "905MAL - Trayus Crescent", "mal_main"); settings.Add("905MAL_unlim", false, "Unlimited Splits", "905MAL"); settings.Add("906MAL", false, "906MAL - Trayus Proving Grounds", "mal_main"); settings.Add("906MAL_unlim", false, "Unlimited Splits", "906MAL"); settings.Add("907MAL", false, "907MAL - Trayus Core (Sion Cutscene)", "mal_main"); settings.Add("907MAL_unlim", false, "Unlimited Splits", "907MAL"); vars.enteredAreas = new List<string>() { "001EBO" }; vars.loading = false; // Create handler for custom timer start offset vars.timerStart = (EventHandler) ((s, e) => { timer.Run.Offset = TimeSpan.FromSeconds(0); }); timer.OnStart += vars.timerStart; } init { // Check game version switch (modules.First().ModuleMemorySize) { case 7049216: version = "Steam"; break; case 7012352: version = "GOG"; break; default: version = "UNKNOWN"; MessageBox.Show(timer.Form, "KotOR 2 autosplitter startup failure. \nCould not recognize what version of the game you are running", "KotOR 2 startup failure", MessageBoxButtons.OK, MessageBoxIcon.Error); break; } vars.loadingCheck = false; vars.isDatapad = false; // Game is not paused at start, and keep timer running if game exits. timer.IsGameTimePaused = false; game.Exited += (s, e) => timer.IsGameTimePaused = false; } start { vars.enteredAreas = new List<string>() { "001EBO" }; vars.didFinalSplit = false; if (current.area == "001EBO" && vars.loading) { // Add predetermined offset to timer // (represents time between pressing "Play" on character creation screen // and the first loading screen appearing) timer.Run.Offset = TimeSpan.FromSeconds(0.735); return true; } } split { // entered a different module if (current.area != old.area) { // check if we're supposed to split on the new area if (settings[current.area.ToUpper()]) { // check if we want to unlimited split if (settings[current.area.ToUpper() + "_unlim"]) { return true; } else if (vars.enteredAreas.Contains(current.area) != true) { vars.enteredAreas.Add(current.area); return true; } } } // Detect Traya Defeated if ( current.area == "904MAL" && current.trayaBattleState == 3 && !vars.didFinalSplit && current.trayaBattleState != old.trayaBattleState ) { vars.didFinalSplit = true; return true; } } update { // perform loading check vars.loadingCheck = (current.isLoading != 0); // remove loading time only if loading screen detected, no active AMG // and current window is valid vars.loading = (vars.loadingCheck == true) && (current.isNotAMG == 0) && (current.isActiveWindow == 1); } isLoading { return vars.loading; } shutdown { timer.OnStart -= vars.timerStart; }