Skip to content

Instantly share code, notes, and snippets.

@wRadion
Created October 31, 2025 13:55
Show Gist options
  • Save wRadion/8c8c29a3d652b5b552df0c5e91d829c4 to your computer and use it in GitHub Desktop.
Save wRadion/8c8c29a3d652b5b552df0c5e91d829c4 to your computer and use it in GitHub Desktop.
Little Nightmares III - AutoSplitter & Load Remover
/**
* AutoSplitter and Load Remover for Little Nightmares III
* v1.0
*
* by Nikko & wRadion
*/
state("LittleNightmaresIII")
{
float xCoord : 0x0643BB38, 0x120, 0x2D8, 0x130, 0x120;
float yCoord : 0x0643BB38, 0x120, 0x2D8, 0x130, 0x11C;
float zCoord : 0x0643BB38, 0x120, 0x2D8, 0x130, 0x124;
float xCoord2 : 0x0643BB38, 0x120, 0x2E8, 0x290, 0x120;
float yCoord2 : 0x0643BB38, 0x120, 0x2E8, 0x290, 0x11C;
float zCoord2 : 0x0643BB38, 0x120, 0x2E8, 0x290, 0x124;
float levelTime : 0x0643BB38, 0x120, 0x2D8, 0x1A0, 0x3F0, 0x288;
}
startup
{
// Chapter 1
settings.Add("chap1", true, "Chapter 1: Necropolis");
settings.Add("chap1_umbrella", true, "Umbrella", "chap1");
settings.Add("chap1_baby_cutscene", true, "Giant Baby Cutscene", "chap1");
settings.Add("chap1_end", true, "Entering Mirror (end)", "chap1");
// Chapter 2
settings.Add("chap2", true, "Chapter 2: Candy Factory");
settings.Add("chap2_supervisor_chase", true, "Falling after Supervisor chase", "chap2");
settings.Add("chap2_lobby_elevator", true, "Lobby Elevator upstairs", "chap2");
settings.Add("chap2_surveillance_exit", true, "Exit Surveillance", "chap2");
settings.Add("chap2_end", true, "Entering Mirror (end)", "chap2");
// Chapter 3
settings.Add("chap3", true, "Chapter 3: Carnevale");
settings.Add("chap3_voc_exit", true, "Exit Vault of Curiosities", "chap3");
settings.Add("chap3_post_cargo_fight", true, "Post Bullies Fight Hatch", "chap3");
settings.Add("chap3_saw_room", true, "Entering Saw Room", "chap3");
settings.Add("chap3_coaster_storage", true, "Entering Coaster Storage", "chap3");
settings.Add("chap3_captured", true, "Captured", "chap3");
settings.Add("chap3_stage_exit", true, "Exiting stage", "chap3");
settings.Add("chap3_end", true, "Balloon Detached (end)", "chap3");
// Chapter 4
settings.Add("chap4", true, "Chapter 4: The Institute");
settings.Add("chap4_alone_doll", true, "Magic Doll cutscene", "chap4");
settings.Add("chap4_psychiatrist", true, "The Psychiatrist face cutscene", "chap4");
settings.Add("chap4_end", true, "Falling after defeating The Psychiatrist (end)", "chap4");
}
init
{
/*
CHAPTER 1
- chap1_umbrella (Labyrinth_ExteriorPathway)
- chap1_baby_cutscene (Labyrinth_BeetleFlight)
- chap1_end (Labyrinth_MirrorRoomTop -> Factory_Hideaway)
CHAPTER 2
- chap2_supervisor_chase (Factory_BalconyCorridor)
- chap2_lobby_elevator (Factory_LobbyLower_0 / Factory_LobbyUpper)
- chap2_surveillance_exit (Factory_SurveillanceExit)
- chap2_end (Factory_MessHallExit -> VOC_EmptyStorageRoom)
CHAPTER 3
- chap3_voc_exit (VOC_CarneCorridor)
- chap3_post_cargo_fight (Carnevale_PostCargoFight)
- chap3_saw_room (Carnevale_SawRoom during zipline, entering SawRoom)
- chap3_coaster_storage (Carnevale_CoastersEnd -> Carnevale_CoasterStorage)
- chap3_captured (Carnevale_PracticeStage_PreKin)
- chap3_stage_exit (Carnevale_StageExitLower)
- chap3_end (balloon detached and flying away)
CHAPTER 4
- chap4_alone_doll (TheCopy_ChildHovel)
- chap4_psychiatrist (TheCopy_EastWingEntryRoom)
- chap4_end (TheCopy_HypnotistFight_02)
*/
vars.completedSplits = new Dictionary<string, bool>();
/*
Checks used to trigger splits with a previous position check
CHAPTER 1
- chap1_umbrella (Labyrinth_ExteriorPathway)
CHAPTER 4
- chap4_alone_doll (TheCopy_ChildHovel)
*/
vars.splitChecks = new Dictionary<string, bool>();
vars.runStarted = false;
Func<float, float, float, float, float, float, float> GetDistance = (x1, y1, z1, x2, y2, z2) => {
float dx = x2 - x1;
float dy = y2 - y1;
float dz = z2 - z1;
return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
};
vars.GetDistance = GetDistance;
Func<float, float, float, float> GetDistanceToCur = (x, y, z) => vars.GetDistance(current.xCoord, current.yCoord, current.zCoord, x, y, z);
vars.GetDistanceToCur = GetDistanceToCur;
Func<string, bool> IsCompleted = (name) => !settings[name] || (vars.completedSplits.ContainsKey(name) && vars.completedSplits[name]);
vars.IsCompleted = IsCompleted;
Func<string, bool> HasCheck = (name) => vars.splitChecks.ContainsKey(name) && vars.splitChecks[name];
vars.HasCheck = HasCheck;
}
onStart
{
vars.completedSplits.Clear();
vars.splitChecks.Clear();
vars.AllGameTime = 0;
vars.runStarted = true;
vars.startGameTime = current.levelTime;
}
onReset
{
vars.completedSplits.Clear();
vars.splitChecks.Clear();
vars.AllGameTime = 0;
vars.runStarted = false;
vars.startGameTime = 0;
}
start
{
if (!vars.runStarted && vars.GetDistanceToCur(-67200f, 2050f, -9050f) <= 500f)
return true;
}
reset
{
if (old.xCoord == 0f && old.yCoord == 0f && old.zCoord == 0f && vars.GetDistanceToCur(-94665f, -23570f, -6650.50f) <= 200f)
return true;
}
split
{
/* CHAPTER 1 */
if (settings["chap1"] && !vars.IsCompleted("chap1_end")) {
// Split for Umbrella
if (!vars.IsCompleted("chap1_umbrella")) {
if (!vars.HasCheck("chap1_umbrella") && vars.GetDistanceToCur(-31890f, 78f, -5629.5f) <= 150f)
vars.splitChecks["chap1_umbrella"] = true;
if (vars.HasCheck("chap1_umbrella") && current.xCoord <= -32000f && -5632.91f <= current.zCoord && current.zCoord <= -5632.89f) {
vars.completedSplits["chap1_umbrella"] = true;
return true;
}
}
// Split for Baby Cutscene (Nightmare)
if (!vars.IsCompleted("chap1_baby_cutscene")) {
if (vars.GetDistance(old.xCoord, old.yCoord, old.zCoord, current.xCoord, current.yCoord, current.zCoord) > 2500f && vars.GetDistanceToCur(3300.00f, -6245.00f, -9760.67f) <= 100f) {
vars.completedSplits["chap1_baby_cutscene"] = true;
return true;
}
}
// Split for Chapter 1 End (entering mirror)
if (vars.GetDistance(old.xCoord, old.yCoord, old.zCoord, current.xCoord, current.yCoord, current.zCoord) > 212000f && vars.GetDistanceToCur(-136467.50f, 590.00f, 37400.50f) <= 150f) {
vars.completedSplits["chap1_end"] = true;
return true;
}
}
/* CHAPTER 2 */
if (settings["chap2"] && !vars.IsCompleted("chap2_end")) {
// Split for Supervisor Chase (fall after opening door)
if (!vars.IsCompleted("chap2_supervisor_chase")) {
if (vars.GetDistanceToCur(-115223f, 2300f, 39835f) <= 100f && current.xCoord > -115200.0f) {
vars.completedSplits["chap2_supervisor_chase"] = true;
return true;
}
}
// Split for Lobby Elevator (exit first elevator)
if (!vars.IsCompleted("chap2_lobby_elevator")) {
if (vars.GetDistanceToCur(-89140f, 3500f, 43980f) <= 500f && current.yCoord < 3480f) {
vars.completedSplits["chap2_lobby_elevator"] = true;
return true;
}
}
// Split for Surveillance Exit
if (!vars.IsCompleted("chap2_surveillance_exit")) {
if (vars.GetDistanceToCur(-77900f, 1623f, 43210f) <= 500f && current.xCoord > -77850f) {
vars.completedSplits["chap2_surveillance_exit"] = true;
return true;
}
}
// Split for Chapter 2 End (entering mirror)
if (!vars.IsCompleted("chap2_end")) {
if (vars.GetDistance(old.xCoord, old.yCoord, old.zCoord, current.xCoord, current.yCoord, current.zCoord) > 12000f && vars.GetDistanceToCur(71900.00f, 850.00f, 39864.50f) <= 500f) {
vars.completedSplits["chap2_end"] = true;
return true;
}
}
}
/* CHAPTER 3 */
if (settings["chap3"] && !vars.IsCompleted("chap3_end")) {
// Split for VaultOfCuriosity Exit (after opening locked door)
if (!vars.IsCompleted("chap3_voc_exit")) {
if (vars.GetDistanceToCur(72772.15f, 164.31f, 46154.96f) <= 200f && current.xCoord < 72700) {
vars.completedSplits["chap3_voc_exit"] = true;
return true;
}
}
// Split for Post Cargo Fight (going into the hatch)
if (!vars.IsCompleted("chap3_post_cargo_fight")) {
if (vars.GetDistanceToCur(76989.89f, 950f, 48800f) <= 500f && current.zCoord <= 49000f) {
vars.completedSplits["chap3_post_cargo_fight"] = true;
return true;
}
}
// Split for entering Saw Room (from zipline or ground w/ caravan skip)
if (!vars.IsCompleted("chap3_saw_room")) {
if (vars.GetDistanceToCur(107000f, 5950f, 49500f) <= 1500f && current.xCoord >= 107050f) {
vars.completedSplits["chap3_saw_room"] = true;
return true;
}
}
// Split for entering Coaster Storage room
if (!vars.IsCompleted("chap3_coaster_storage")) {
if (vars.GetDistanceToCur(126624f, 66130f, 47664f) <= 100f && current.xCoord >= 126700f) {
vars.completedSplits["chap3_coaster_storage"] = true;
return true;
}
}
// Split for after capture cutscene (in practice stage)
if (!vars.IsCompleted("chap3_captured")) {
if (vars.GetDistance(old.xCoord, old.yCoord, old.zCoord, current.xCoord, current.yCoord, current.zCoord) > 25000f && vars.GetDistanceToCur(179300f, 65300f, 64650f) <= 1000f) {
vars.completedSplits["chap3_captured"] = true;
return true;
}
}
// Split for Stage Exit (locked door)
if (!vars.IsCompleted("chap3_stage_exit")) {
if (vars.GetDistanceToCur(194050f, 64958f, 64541f) <= 200f && current.xCoord > 194080f) {
vars.completedSplits["chap3_stage_exit"] = true;
return true;
}
}
// Spit for Chapter 3 ending (balloon detached)
if (!vars.IsCompleted("chap3_end")) {
if (vars.GetDistanceToCur(204750f, 56158f, 67000f) <= 500f && current.zCoord > 67000f) {
vars.completedSplits["chap3_end"] = true;
return true;
}
}
}
if (settings["chap4"] && !vars.IsCompleted("chap4_end")) {
// Split for Alone Doll (time doll)
if (!vars.IsCompleted("chap4_alone_doll")) {
if (!vars.HasCheck("chap4_alone_doll") && vars.GetDistanceToCur(250000f, -34680f, 111694f) <= 200f && current.yCoord == -34680.00000f && current.yCoord2 == -34680.00000f)
vars.splitChecks["chap4_alone_doll"] = true;
if (vars.HasCheck("chap4_alone_doll") && (current.zCoord >= 111848f || current.zCoord2 >= 111848f)) {
vars.completedSplits["chap4_alone_doll"] = true;
return true;
}
}
// Split for The Psychiatrist (face reveal cutscene)
if (!vars.IsCompleted("chap4_psychiatrist")) {
if (vars.GetDistanceToCur(275100f, -24300f, 110287f) <= 200f && (current.xCoord > 275122f || current.xCoord2 > 275122f)) {
vars.completedSplits["chap4_psychiatrist"] = true;
return true;
}
}
// Split for Falling after defeating The Psychiatrist
if (!vars.IsCompleted("chap4_end")) {
if (vars.GetDistanceToCur(308932f, -42182f, 100450f) <= 5000f && current.zCoord < 100000f) {
vars.completedSplits["chap4_end"] = true;
return true;
}
}
}
}
isLoading
{
return true;
}
gameTime
{
if (old.levelTime > current.levelTime)
vars.AllGameTime += old.levelTime;
if (current.levelTime >= 0 && vars.runStarted)
return TimeSpan.FromSeconds(vars.AllGameTime+current.levelTime-vars.startGameTime);
else if (!vars.runStarted)
return TimeSpan.FromSeconds(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment