state("POP2") { // This variable is 0 during gameplay, 1 in cutscenes, 2 when a cutscene ends int cutscene : 0x9665D0, 0x18, 0x4, 0x48, 0xE0; // Story counter/gate/value int storyValue : 0x523578; // A value that changes reliably depending on which weapon you pick up int secondaryWeapon : 0x53F8F0, 0x4, 0x164, 0xC, 0x364; // The address used for most bosses' health int bossHealth : 0x90C418, 0x18, 0x4, 0x48, 0x198; // The Prince's coords float xPos : 0x90C414, 0x18, 0x0, 0x4, 0x20, 0x30; float yPos : 0x90C414, 0x18, 0x0, 0x4, 0x20, 0x34; float zPos : 0x90C414, 0x18, 0x0, 0x4, 0x20, 0x38; // Currently loaded area id (changes with every load trigger) int map : 0x523594; // State of the prince (11 is drinking) int state : 0x90C414, 0x18, 0x4, 0x48, 0x3F8; // Gallery trackers ulong chestBits : 0x8D2EA8; ulong weaponBits : 0x8D2EB0; } startup { vars.splitTypes = new Dictionary { { "AnyGlitched", "Any% (Standard) and Any% (Zipless) splits" }, { "AnyNMG", "Any% (No Major Glitches) splits" }, { "TEStandard", "True Ending (Standard) splits" }, { "TEZipless", "True Ending (Zipless) splits" }, { "TENMG", "True Ending (No Major Glitches) splits" }, }; // Key - Setting ID, Value - Tuple of (Default setting, Description, Split type, Tooltip and Trigger condition). // The keys have been named the way they are to not mess-up users' already set settings. // To anyone looking add new splits - please make the key descriptive too, it won't affect anything already added. vars.splitsData = new Dictionary>> { { "Any0", Tuple.Create(true, "Boat", "AnyGlitched", "Split when the boat ending cutscene starts playing", new Func(() => vars.boat() )) }, { "Any1", Tuple.Create(true, "Raven man", "AnyGlitched", "Split on the cutscene where you're introduced to a raven master", new Func(() => vars.ravenMan() )) }, { "Any2", Tuple.Create(true, "Time portal", "AnyGlitched", "Split when you go through the first time portal", new Func(() => vars.firstPortal() )) }, { "Any3", Tuple.Create(true, "Foundy fountain", "AnyGlitched", "Split when you drink from the foundry fountain while having 58/59 storygate", new Func(() => vars.foundryFountain() )) }, { "Any4", Tuple.Create(true, "Scorpion sword", "AnyGlitched", "Split when you get the scorpion sword", new Func(() => vars.scorpionSword() )) }, { "Any5", Tuple.Create(false, "Light sword", "AnyGlitched", "Split when you pick up the light sword in mystic caves", new Func(() => vars.banana() )) }, { "Any6", Tuple.Create(true, "Mechanical tower (63)", "AnyGlitched", "Split when you acquire storygate 63", new Func(() => vars.rng63() )) }, { "Any7", Tuple.Create(true, "Second portal", "AnyGlitched", "Split when you go through the time portal in the throne room", new Func(() => vars.lastPortal() )) }, { "Any8", Tuple.Create(true, "Kaileena", "AnyGlitched", "Split when you kill Kaileena in sacred caves", new Func(() => vars.kaileena() )) }, { "TeStandard0", Tuple.Create(true, "Boat", "TEStandard", "Split when the boat ending cutscene starts playing", new Func(() => vars.boat() )) }, { "TeStandard1", Tuple.Create(true, "Raven man", "TEStandard", "Split on the cutscene where you're introduced to a raven master", new Func(() => vars.ravenMan() )) }, { "TeStandard2", Tuple.Create(true, "Time portal", "TEStandard", "Split when you go through the first time portal", new Func(() => vars.firstPortal() )) }, { "TeStandard3", Tuple.Create(true, "(1) fortress entrance LU", "TEStandard", "Split when you acquire the life upgrade in fortress entrance", new Func(() => vars.LUFortress() )) }, { "TeStandard4", Tuple.Create(true, "(2) Prison LU", "TEStandard", "Split when you acquire the life upgrade in prison", new Func(() => vars.LUPrison() )) }, { "TeStandard5", Tuple.Create(true, "(3) Library LU", "TEStandard", "Split when you acquire the life upgrade in library", new Func(() => vars.LULibrary() )) }, { "TeStandard6", Tuple.Create(true, "(4) Mechanical tower LU", "TEStandard", "Split when you acquire the life upgrade in mechanical tower", new Func(() => vars.LUMechTower() )) }, { "TeStandard7", Tuple.Create(true, "(5) Garden LU", "TEStandard", "Split when you acquire the life upgrade in garden", new Func(() => vars.LUGarden() )) }, { "TeStandard8", Tuple.Create(true, "(6) Waterworks LU", "TEStandard", "Split when you acquire the life upgrade in waterworks", new Func(() => vars.LUWaterworks() )) }, { "TeStandard9", Tuple.Create(true, "(7) Sacrificial altar LU", "TEStandard", "Split when you acquire the life upgrade in sacrificial altar", new Func(() => vars.LUShahdee() )) }, { "TeStandard10", Tuple.Create(true, "(8) Southern passage LU", "TEStandard", "Split when you acquire the life upgrade in southern passage", new Func(() => vars.LU019() )) }, { "TeStandard11", Tuple.Create(true, "(9) Central hall LU", "TEStandard", "Split when you acquire the life upgrade in central hall", new Func(() => vars.LUCentralHall() )) }, { "TeStandard12", Tuple.Create(true, "Water sword", "TEStandard", "Split when you get the water sword", new Func(() => vars.WaterSword() )) }, { "TeStandard13", Tuple.Create(true, "Dahaka", "TEStandard", "Split when you defeat Dahaka", new Func(() => vars.Dahaka() )) }, { "TeZipless0", Tuple.Create(true, "Boat", "TEZipless", "Split when the boat ending cutscene starts playing", new Func(() => vars.boat() )) }, { "TeZipless1", Tuple.Create(true, "Raven man", "TEZipless", "Split on the cutscene where you're introduced to a raven master", new Func(() => vars.ravenMan() )) }, { "TeZipless2", Tuple.Create(false, "Time portal", "TEZipless", "Split when you go through the first time portal", new Func(() => vars.firstPortal() )) }, { "TeZipless3", Tuple.Create(true, "(1) Central hall LU", "TEZipless", "Split when you acquire the life upgrade in central hall", new Func(() => vars.LUCentralHall() )) }, { "TeZipless4", Tuple.Create(true, "(2) Waterworks LU", "TEZipless", "Split when you acquire the life upgrade in waterworks", new Func(() => vars.LUWaterworks() )) }, { "TeZipless5", Tuple.Create(true, "(3) Garden LU", "TEZipless", "Split when you acquire the life upgrade in garden", new Func(() => vars.LUGarden() )) }, { "TeZipless6", Tuple.Create(true, "(4) Fortress entrance LU", "TEZipless", "Split when you acquire the life upgrade in fortress entrance", new Func(() => vars.LUFortress() )) }, { "TeZipless7", Tuple.Create(true, "Foundry (59)", "TEZipless", "Split when you acquire storygate 59", new Func(() => vars.rng59() )) }, { "TeZipless8", Tuple.Create(true, "(5) Prison LU", "TEZipless", "Split when you acquire the life upgrade in prison", new Func(() => vars.LUPrison() )) }, { "TeZipless9", Tuple.Create(true, "(6) Library LU", "TEZipless", "Split when you acquire the life upgrade in library", new Func(() => vars.LULibrary() )) }, { "TeZipless10", Tuple.Create(false, "Light sword", "TEZipless", "Split when you pick up the light sword in mystic caves", new Func(() => vars.banana() )) }, { "TeZipless11", Tuple.Create(true, "Mechanical tower (63)", "TEZipless", "Split when you acquire storygate 63", new Func(() => vars.rng63() )) }, { "TeZipless12", Tuple.Create(true, "(7) Mechanical tower LU", "TEZipless", "Split when you acquire the life upgrade in mechanical tower", new Func(() => vars.LUMechTower() )) }, { "TeZipless13", Tuple.Create(true, "(8) Southern passage LU", "TEZipless", "Split when you acquire the life upgrade in southern passage", new Func(() => vars.LU019() )) }, { "TeZipless14", Tuple.Create(true, "(9) Sacrificial altar LU", "TEZipless", "Split when you acquire the life upgrade in sacrificial altar", new Func(() => vars.LUShahdee() )) }, { "TeZipless15", Tuple.Create(true, "Water sword", "TEZipless", "Split when you get the water sword", new Func(() => vars.WaterSword() )) }, { "TeZipless16", Tuple.Create(true, "Dahaka", "TEZipless", "Split when you defeat Dahaka", new Func(() => vars.Dahaka() )) }, { "AnyNmg0", Tuple.Create(true, "Boat", "AnyNMG", "Split when the boat ending cutscene starts playing", new Func(() => vars.boat() )) }, { "AnyNmg1", Tuple.Create(true, "Spider sword", "AnyNMG", "Split on the cutscene where you get the spider sword", new Func(() => vars.spiderSword() )) }, { "AnyNmg2", Tuple.Create(false, "Raven man", "AnyNMG", "Split on the cutscene where you're introduced to a raven master", new Func(() => vars.ravenMan() )) }, { "AnyNmg3", Tuple.Create(false, "Time portal", "AnyNMG", "Split when you go through the first time portal", new Func(() => vars.firstPortal() )) }, { "AnyNmg4", Tuple.Create(true, "Soutern passage (chasing Shahdee)", "AnyNMG", "Split when you come to southern passage past", new Func(() => vars.chasingShahdee() )) }, { "AnyNmg5", Tuple.Create(true, "Shahdee (a damsel in distress)", "AnyNMG", "Split when you kill Shahdee", new Func(() => vars.shahdee() )) }, { "AnyNmg_spPortalEnter", Tuple.Create(false, "Enter Southern Passage Portal", "AnyNMG", "Split when you enter the portal in Southern Passage", new Func(() => vars.spPortalEnter() )) }, { "AnyNmg_spPortalExit", Tuple.Create(false, "Exit Southern Passage Portal", "AnyNMG", "Split when you exit the portal in Southern Passage", new Func(() => vars.spPortalExit() )) }, { "AnyNmg6", Tuple.Create(true, "The Dahaka", "AnyNMG", "Split on the cutscene before the first Dahaka chase (southern passage present)", new Func(() => vars.princeStare() )) }, { "AnyNmg7", Tuple.Create(true, "Serpent sword", "AnyNMG", "Split on the cutscene where you get the serpent sword (hourglass chamber)", new Func(() => vars.serpentSword() )) }, { "AnyNmg8", Tuple.Create(true, "Garden hall", "AnyNMG", "Split when you come to garden hall", new Func(() => vars.gardenHall() )) }, { "AnyNmg9", Tuple.Create(true, "Waterworks", "AnyNMG", "Split when you come to garden waterworks", new Func(() => vars.waterworks() )) }, { "AnyNmg10", Tuple.Create(true, "Lion sword", "AnyNMG", "Split on the cutscene where you get the lion sword (central hall)", new Func(() => vars.lionSword() )) }, { "AnyNmg11", Tuple.Create(true, "Mechanical tower", "AnyNMG", "Split when you clilmb up into the mechanical tower", new Func(() => vars.mechTower() )) }, { "AnyNmg12", Tuple.Create(false, "Mechanical tower v2 (elevator cutscene)", "AnyNMG", "Split on the cutscene where you jump down on the elevator at the start of mech tower", new Func(() => vars.mechElevator() )) }, { "AnyNmg_mpPortalEnter", Tuple.Create(false, "Enter Mechanical Pit Portal", "AnyNMG", "Split when you enter the portal in Mechanical Pit", new Func(() => vars.mpPortalEnter() )) }, { "AnyNmg13", Tuple.Create(true, "Mechanical Pit Portal", "AnyNMG", "Split when you go through the time portal in mechanical pit", new Func(() => vars.mechPortal() )) }, { "AnyNmg_mpPortalExit", Tuple.Create(false, "Exit Mechanical Pit Portal", "AnyNMG", "Split when you exit the portal in Mechanical Pit", new Func(() => vars.mpPortalExit() )) }, { "AnyNmg14", Tuple.Create(true, "Activation room in ruin", "AnyNMG", "Split when you come to the mech tower activation room in the present", new Func(() => vars.activationRuin() )) }, { "AnyNmg_arPortalEnter", Tuple.Create(false, "Enter Activation room Portal", "AnyNMG", "Split when you enter the portal in Activation room", new Func(() => vars.arPortalEnter() )) }, { "AnyNmg_arPortalExit", Tuple.Create(false, "Exit Activation room Portal", "AnyNMG", "Split when you exit the portal in Activation room", new Func(() => vars.arPortalExit() )) }, { "AnyNmg15", Tuple.Create(true, "Activation room restored", "AnyNMG", "Split when you come to the mech tower activation room in the past", new Func(() => vars.activationRestore() )) }, { "AnyNmg16", Tuple.Create(true, "The death of a sand wraith (central hall)", "AnyNMG", "Split in central hall next to the fountain after you've activated both towers", new Func(() => vars.sandWraithDeathV1() )) }, { "AnyNmg17", Tuple.Create(false, "The death of a sand wraith v2 (central hall)", "AnyNMG", "Alternate split located deeper into the corridor so you can't hit it early when jumping down", new Func(() => vars.sandWraithDeathV2() )) }, { "AnyNmg18", Tuple.Create(true, "Death of the empress", "AnyNMG", "Split when you kill Kaileena in the throne room (34->38)", new Func(() => vars.kaileenaFirst() )) }, { "AnyNmg19", Tuple.Create(true, "Exit the tomb", "AnyNMG", "Split when you leave the tomb", new Func(() => vars.exitTomb() )) }, { "AnyNmg_prPortalEnter", Tuple.Create(false, "Enter Prison Portal", "AnyNMG", "Split when you enter the portal in Prison", new Func(() => vars.prPortalEnter() )) }, { "AnyNmg_prPortalExit", Tuple.Create(false, "Exit Prison Portal", "AnyNMG", "Split when you exit the portal in Prison", new Func(() => vars.prPortalExit() )) }, { "AnyNmg20", Tuple.Create(true, "Scorpion sword", "AnyNMG", "Split when you get the scorpion sword", new Func(() => vars.scorpionSword() )) }, { "AnyNmg21", Tuple.Create(false, "Library", "AnyNMG", "Split on the library opening cutscene", new Func(() => vars.libraryV1() )) }, { "AnyNmg22", Tuple.Create(true, "Library v2", "AnyNMG", "Split when you move into the library (after the opening cutscene)", new Func(() => vars.libraryV2() )) }, { "AnyNmg23", Tuple.Create(true, "Hourglass revisited", "AnyNMG", "Split when you come back to the hourglass chamber after you've killed Kaileena", new Func(() => vars.hourglassRevisit() )) }, { "AnyNmg_trPortalEnter", Tuple.Create(false, "Enter Throne Room Portal", "AnyNMG", "Split when you enter the cutscene after breaking Throne Room wall", new Func(() => vars.trPortalEnter() )) }, { "AnyNmg_trPortalExit", Tuple.Create(false, "Exit Throne Room Portal", "AnyNMG", "Split when you exit the portal in Throne Room", new Func(() => vars.trPortalExit() )) }, { "AnyNmg24", Tuple.Create(true, "The mask of the wraith", "AnyNMG", "Split when you get to the mask", new Func(() => vars.maskOn() )) }, { "AnyNmg_scPortalEnter", Tuple.Create(false, "Enter Sacred Caves Portal", "AnyNMG", "Split when you enter the portal in Sacred Caves", new Func(() => vars.scPortalEnter() )) }, { "AnyNmg_scPortalExit", Tuple.Create(false, "Exit Sacred Caves Portal", "AnyNMG", "Split when you exit the portal in Sacred Caves", new Func(() => vars.scPortalExit() )) }, { "AnyNmg25", Tuple.Create(true, "Sand griffin", "AnyNMG", "Split when you kill the griffin", new Func(() => vars.griffinV1() )) }, { "AnyNmg26", Tuple.Create(false, "Sand griffin v2", "AnyNMG", "Split when you jump to the platform after you've killed the griffin", new Func(() => vars.griffinV2() )) }, { "AnyNmg_ugPortalEnter", Tuple.Create(false, "Enter Upper Garden Portal", "AnyNMG", "Split when you enter the portal in Upper Garden", new Func(() => vars.ugPortalEnter() )) }, { "AnyNmg_ugPortalExit", Tuple.Create(false, "Exit Upper Garden Portal", "AnyNMG", "Split when you exit the portal in Upper Garden", new Func(() => vars.ugPortalExit() )) }, { "AnyNmg27", Tuple.Create(true, "Mirrored fates", "AnyNMG", "Split on the sacrificial altar cutscene (sand wraith pov)", new Func(() => vars.mirroredFates() )) }, { "AnyNmg28", Tuple.Create(true, "A favor unknown", "AnyNMG", "Split on the cutscene where the sand wraith saves the prince by throwing an axe (sand wraith pov)", new Func(() => vars.favorUnknown() )) }, { "AnyNmg29", Tuple.Create(true, "Library revisited", "AnyNMG", "Split when you enter the library", new Func(() => vars.libraryRevisit() )) }, { "AnyNmg30", Tuple.Create(true, "Light sword", "AnyNMG", "Split when you pick up the light sword in mystic caves", new Func(() => vars.banana() )) }, { "AnyNmg31", Tuple.Create(true, "The death of a prince", "AnyNMG", "Split on the cutscene where you take the mask off", new Func(() => vars.maskOff() )) }, { "AnyNmg32", Tuple.Create(true, "Kaileena", "AnyNMG", "Split when you kill Kaileena in sacred caves", new Func(() => vars.kaileena() )) }, { "TeNmg0", Tuple.Create(true, "Boat", "TENMG", "Split when the boat ending cutscene starts playing", new Func(() => vars.boat() )) }, { "TeNmg1", Tuple.Create(true, "Spider sword", "TENMG", "Split on the cutscene where you get the spider sword", new Func(() => vars.spiderSword() )) }, { "TeNmg2", Tuple.Create(false, "Raven man", "TENMG", "Split on the cutscene where you're introduced to a raven master", new Func(() => vars.ravenMan() )) }, { "TeNmg3", Tuple.Create(false, "Time portal", "TENMG", "Split when you go through the first time portal", new Func(() => vars.firstPortal() )) }, { "TeNmg4", Tuple.Create(true, "Soutern passage (chasing Shahdee)", "TENMG", "Split when you come to southern passage past", new Func(() => vars.chasingShahdee() )) }, { "TeNmg5", Tuple.Create(true, "(1) Southern passage LU", "TENMG", "Split when you acquire the life upgrade in southern passage", new Func(() => vars.LU019() )) }, { "TeNmg6", Tuple.Create(true, "Shahdee (a damsel in distress)", "TENMG", "Split when you kill Shahdee", new Func(() => vars.shahdee() )) }, { "TeNmg7", Tuple.Create(true, "(2) Sacrificial alter LU", "TENMG", "Split when you acquire the life upgrade in sacrificial altar", new Func(() => vars.LUShahdee() )) }, { "TeNmg_spPortalEnter", Tuple.Create(false, "Enter Southern Passage Portal", "TENMG", "Split when you enter the portal in Southern Passage", new Func(() => vars.spPortalEnter() )) }, { "TeNmg_spPortalExit", Tuple.Create(false, "Exit Southern Passage Portal", "TENMG", "Split when you exit the portal in Southern Passage", new Func(() => vars.spPortalExit() )) }, { "TeNmg8", Tuple.Create(true, "The Dahaka", "TENMG", "Split on the cutscene before the first Dahaka chase (southern passage present)", new Func(() => vars.princeStare() )) }, { "TeNmg9", Tuple.Create(true, "(3) Fortress entrance LU", "TENMG", "Split when you acquire the life upgrade in fortress entrance", new Func(() => vars.LUFortress() )) }, { "TeNmg10", Tuple.Create(true, "Serpent sword", "TENMG", "Split on the cutscene where you get the serpent sword (hourglass chamber)", new Func(() => vars.serpentSword() )) }, { "TeNmg11", Tuple.Create(true, "Garden hall", "TENMG", "Split when you come to garden hall", new Func(() => vars.gardenHall() )) }, { "TeNmg12", Tuple.Create(false, "Waterworks", "TENMG", "Split when you come to garden waterworks", new Func(() => vars.waterworks() )) }, { "TeNmg13", Tuple.Create(true, "(4) Waterworks LU", "TENMG", "Split when you acquire the life upgrade in waterworks", new Func(() => vars.LUWaterworks() )) }, { "TeNmg15", Tuple.Create(true, "(5) Garden LU", "TENMG", "Split when you acquire the life upgrade in garden", new Func(() => vars.LUGarden() )) }, { "TeNmg16", Tuple.Create(true, "(6) Central hall LU", "TENMG", "Split when you acquire the life upgrade in central hall", new Func(() => vars.LUCentralHall() )) }, { "TeNmg17", Tuple.Create(false, "Lion sword", "TENMG", "Split on the cutscene where you get the lion sword (central hall)", new Func(() => vars.lionSword() )) }, { "TeNmg18", Tuple.Create(true, "Mechanical tower", "TENMG", "Split when you clilmb up into the mechanical tower", new Func(() => vars.mechTower() )) }, { "TeNmg19", Tuple.Create(false, "Mechanical tower v2 (elevator cutscene)", "TENMG", "Split on the cutscene where you jump down on the elevator at the start of mech tower", new Func(() => vars.mechElevator() )) }, { "TeNmg_mpPortalEnter", Tuple.Create(false, "Enter Mechanical Pit Portal", "TENMG", "Split when you enter the portal in Mechanical Pit", new Func(() => vars.mpPortalEnter() )) }, { "TeNmg20", Tuple.Create(true, "Mechanical Pit Portal", "TENMG", "Split when you go through the time portal in mechanical pit", new Func(() => vars.mechPortal() )) }, { "TeNmg_mpPortalExit", Tuple.Create(false, "Exit Mechanical Pit Portal", "TENMG", "Split when you exit the portal in Mechanical Pit", new Func(() => vars.mpPortalExit() )) }, { "TeNmg21", Tuple.Create(true, "Activation room in ruin", "TENMG", "Split when you come to the mech tower activation room in the present", new Func(() => vars.activationRuin() )) }, { "TeNmg_arPortalEnter", Tuple.Create(false, "Enter Activation room Portal", "TENMG", "Split when you enter the portal in Activation room", new Func(() => vars.arPortalEnter() )) }, { "TeNmg_arPortalExit", Tuple.Create(false, "Exit Activation room Portal", "TENMG", "Split when you exit the portal in Activation room", new Func(() => vars.arPortalExit() )) }, { "TeNmg22", Tuple.Create(false, "Activation room restored", "TENMG", "Split when you come to the mech tower activation room in the past", new Func(() => vars.activationRestore() )) }, { "TeNmg23", Tuple.Create(true, "(7) Mechanical tower LU", "TENMG", "Split when you acquire the life upgrade in mechanical tower", new Func(() => vars.LUMechTower() )) }, { "TeNmg24", Tuple.Create(true, "The death of a sand wraith (central hall)", "TENMG", "Split in central hall next to the fountain after you've activated both towers", new Func(() => vars.sandWraithDeathV1() )) }, { "TeNmg25", Tuple.Create(false, "The death of a sand wraith v2 (central hall)", "TENMG", "Alternate split located deeper into the corridor so you can't hit it early when jumping down", new Func(() => vars.sandWraithDeathV2() )) }, { "TeNmg26", Tuple.Create(true, "Death of the empress", "TENMG", "Split when you kill Kaileena in the throne room (34->38)", new Func(() => vars.kaileenaFirst() )) }, { "TeNmg27", Tuple.Create(true, "Exit the tomb", "TENMG", "Split when you leave the tomb", new Func(() => vars.exitTomb() )) }, { "TeNmg_prPortalEnter", Tuple.Create(false, "Enter Prison Portal", "TENMG", "Split when you enter the portal in Prison", new Func(() => vars.prPortalEnter() )) }, { "TeNmg_prPortalExit", Tuple.Create(false, "Exit Prison Portal", "TENMG", "Split when you exit the portal in Prison", new Func(() => vars.prPortalExit() )) }, { "TeNmg28", Tuple.Create(true, "Scorpion sword", "TENMG", "Split when you get the scorpion sword", new Func(() => vars.scorpionSword() )) }, { "TeNmg29", Tuple.Create(true, "(8) Prison LU", "TENMG", "Split when you acquire the life upgrade in prison", new Func(() => vars.LUPrison() )) }, { "TeNmg30", Tuple.Create(false, "Library", "TENMG", "Split on the library opening cutscene", new Func(() => vars.libraryV1() )) }, { "TeNmg31", Tuple.Create(false, "Library v2", "TENMG", "Split when you move into the library (after the opening cutscene)", new Func(() => vars.libraryV2() )) }, { "TeNmg32", Tuple.Create(true, "(9) Library LU", "TENMG", "Split when you acquire the life upgrade in library", new Func(() => vars.LULibrary() )) }, { "TeNmg33", Tuple.Create(false, "Hourglass revisited", "TENMG", "Split when you come back to the hourglass chamber after you've killed Kaileena", new Func(() => vars.hourglassRevisit() )) }, { "TeNmg34", Tuple.Create(true, "Water sword", "TENMG", "Split when you get the water sword", new Func(() => vars.WaterSword() )) }, { "TeNmg_trPortalEnter", Tuple.Create(false, "Enter Throne Room Portal", "TENMG", "Split when you enter the cutscene after breaking Throne Room wall", new Func(() => vars.trPortalEnter() )) }, { "TeNmg_trPortalExit", Tuple.Create(false, "Exit Throne Room Portal", "TENMG", "Split when you exit the portal in Throne Room", new Func(() => vars.trPortalExit() )) }, { "TeNmg35", Tuple.Create(true, "The mask of the wraith", "TENMG", "Split when you get to the mask", new Func(() => vars.maskOn() )) }, { "TeNmg_scPortalEnter", Tuple.Create(false, "Enter Sacred Caves Portal", "TENMG", "Split when you enter the portal in Sacred Caves", new Func(() => vars.scPortalEnter() )) }, { "TeNmg_scPortalExit", Tuple.Create(false, "Exit Sacred Caves Portal", "TENMG", "Split when you exit the portal in Sacred Caves", new Func(() => vars.scPortalExit() )) }, { "TeNmg36", Tuple.Create(true, "Sand griffin", "TENMG", "Split when you kill the griffin", new Func(() => vars.griffinV1() )) }, { "TeNmg37", Tuple.Create(false, "Sand griffin v2", "TENMG", "Split when you jump to the platform after you've killed the griffin", new Func(() => vars.griffinV2() )) }, { "TeNmg_ugPortalEnter", Tuple.Create(false, "Enter Upper Garden Portal", "TENMG", "Split when you enter the portal in Upper Garden", new Func(() => vars.ugPortalEnter() )) }, { "TeNmg_ugPortalExit", Tuple.Create(false, "Exit Upper Garden Portal", "TENMG", "Split when you exit the portal in Upper Garden", new Func(() => vars.ugPortalExit() )) }, { "TeNmg38", Tuple.Create(true, "Mirrored fates", "TENMG", "Split on the sacrificial altar cutscene (sand wraith pov)", new Func(() => vars.mirroredFates() )) }, { "TeNmg39", Tuple.Create(true, "A favor unknown", "TENMG", "Split on the cutscene where the sand wraith saves the prince by throwing an axe (sand wraith pov)", new Func(() => vars.favorUnknown() )) }, { "TeNmg40", Tuple.Create(true, "Library revisited", "TENMG", "Split when you enter the library", new Func(() => vars.libraryRevisit() )) }, { "TeNmg41", Tuple.Create(true, "Light sword", "TENMG", "Split when you pick up the light sword in mystic caves", new Func(() => vars.banana() )) }, { "TeNmg42", Tuple.Create(true, "The death of a prince", "TENMG", "Split on the cutscene where you take the mask off", new Func(() => vars.maskOff() )) }, { "TeNmg43", Tuple.Create(true, "Dahaka", "TENMG", "Split when you defeat Dahaka", new Func(() => vars.Dahaka() )) }, }; foreach (var splitType in vars.splitTypes) { settings.Add(splitType.Key, false, splitType.Value); } foreach (var data in vars.splitsData) { settings.Add(data.Key, data.Value.Item1, data.Value.Item2, data.Value.Item3); settings.SetToolTip(data.Key, data.Value.Item4); } vars.CompletedSplits = new HashSet(); if (timer.CurrentTimingMethod != TimingMethod.RealTime) { DialogResult mbox = MessageBox.Show(timer.Form, "This game uses only real time as the timing method.\nWould you like to switch to Real Time?", "LiveSplit | Prince of Persia: Warrior Within", MessageBoxButtons.YesNo); if (mbox == DialogResult.Yes) { timer.CurrentTimingMethod = TimingMethod.RealTime; } } } init { // Hamming Weight algorithm vars.countBits = (Func)((x) => { x = x - ((x >> 1) & 0x5555555555555555UL); x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL); x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0FUL; x = x + (x >> 8); x = x + (x >> 16); x = x + (x >> 32); return (int)(x & 0x7F); }); vars.splitCutsceneByMap = (Func, bool>)((mapIds) => { return (mapIds.Contains(current.map) && vars.oldCutscene == 0 && current.cutscene == 1); }); vars.splitBossByMap = (Func, bool>)((mapIds) => { return (vars.splitCutsceneByMap(mapIds) && current.bossHealth == 0); }); vars.splitFountainByStory = (Func, bool>)((storyGates) => { return (storyGates.Contains(current.storyValue) && vars.oldState != 11 && current.state == 11); }); vars.splitByMapSecondary = (Func, int, bool>)((mapIds, secondaryId) => { return (mapIds.Contains(current.map) && vars.oldSecondary != secondaryId && current.secondaryWeapon == secondaryId); }); vars.splitByStoryGate = (Func)((storyId) => { return (vars.oldStory != storyId && current.storyValue == storyId); }); vars.inXRange = (Func)((xMin, xMax) => { return current.xPos >= xMin && current.xPos <= xMax; }); vars.inYRange = (Func)((yMin, yMax) => { return current.yPos >= yMin && current.yPos <= yMax; }); vars.inZRange = (Func)((zMin, zMax) => { return current.zPos >= zMin && current.zPos <= zMax; }); vars.splitByXYZ = (Func)((xMin, xMax, yMin, yMax, zMin, zMax) => { return vars.inXRange(xMin, xMax) && vars.inYRange(yMin, yMax) && vars.inZRange(zMin, zMax); }); vars.getTrackerText = (Func)((bits, expectedBits) => { int count = vars.countBits(bits & expectedBits); int maxCount = vars.countBits(expectedBits); return (count.ToString() + " / " + maxCount.ToString()); }); // List of Splits vars.boat = (Func)(() => { return vars.splitBossByMap(new HashSet { 67109218 }); }); vars.ravenMan = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135462572 }); }); vars.firstPortal = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 285231807 }); }); vars.foundryFountain = (Func)(() => { return vars.splitFountainByStory(new HashSet { 58, 59 }); }); vars.scorpionSword = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135483948, 135483950, 135505359, 135516393, 16809649 }) && current.xPos < -164; }); vars.banana = (Func)(() => { return vars.splitByMapSecondary(new HashSet { 587202754, 587203393 }, 50); }); vars.rng63 = (Func)(() => { return vars.splitByStoryGate(63); }); vars.lastPortal = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { -1509855113, 285233488 }); }); vars.kaileena = (Func)(() => { return vars.splitBossByMap(new HashSet { 989966866 }); }); vars.LUFortress = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135501679 }); }); vars.LUPrison = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135483948, 135516393, 16809649 }) && current.xPos > -120; }); vars.LULibrary = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67144064, 67144084 }); }); vars.LUMechTower = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67145445 }); }); vars.LUGarden = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 1006690753, 1006690755 }); }); vars.LUWaterworks = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 687877046, 687877489 }) && current.xPos > 70; }); vars.LUShahdee = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 285225347, 1006717295 }); }); vars.LU019 = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 989860398, 1006711848 }); }); vars.LUCentralHall = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67144144 }); }); vars.WaterSword = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 1006704427, 1006704429 }) && vars.oldX > -98; }); vars.Dahaka = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 989966868 }) && current.yPos > 200; }); vars.rng59 = (Func)(() => { return vars.splitByStoryGate(59); }); vars.spiderSword = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135462576 }); }); vars.chasingShahdee = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 989860400 }); }); vars.shahdee = (Func)(() => { return vars.splitBossByMap(new HashSet { 1006801609 }); }); vars.spPortalEnter = (Func)(() => { return vars.splitByXYZ(95.5f, 97.5f, -107f, -106f, 413.8f, 414.2f); }); vars.spPortalExit = (Func)(() => { return vars.splitByXYZ(95.5f, 97.5f, -107f, -106f, 113.8f, 114.2f); }); vars.princeStare = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 989884886 }); }); vars.serpentSword = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 1006704429 }) && current.storyValue == 13; }); vars.gardenHall = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135495097, 135495099 }); }); vars.waterworks = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 687877048 }); }); vars.lionSword = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67112526 }) && current.storyValue == 21; }); vars.mechTower = (Func)(() => { return current.map == 687876481 && vars.oldZ < 410 && current.zPos >= 410; }); vars.mechElevator = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 687876652 }); }); vars.mpPortalEnter = (Func)(() => { return vars.splitByXYZ(-211f, -209f, 139f, 141f, 440.8f, 441.2f); }); vars.mechPortal = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 285235400 }); }); vars.mpPortalExit = (Func)(() => { return vars.splitByXYZ(-211f, -209f, 139f, 141f, 140.8f, 141.2f); }); vars.activationRuin = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67145437 }); }); vars.arPortalEnter = (Func)(() => { return vars.splitByXYZ(-172f, -170f, 188f, 189f, 181.8f, 182.2f); }); vars.arPortalExit = (Func)(() => { return vars.splitByXYZ(-172f, -170f, 188f, 189f, 481.8f, 482.2f); }); vars.activationRestore = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67145455 }); }); vars.sandWraithDeathV1 = (Func)(() => { return current.map == 67112526 && vars.oldY < -13 && current.yPos >= -13 && current.zPos < 391 && current.storyValue == 33; }); vars.sandWraithDeathV2 = (Func)(() => { return current.map == 67112526 && vars.oldY < -8 && current.yPos >= -8 && current.storyValue == 33; }); vars.kaileenaFirst = (Func)(() => { return vars.splitByStoryGate(38); }); vars.exitTomb = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135464247 }) && current.zPos > 33; }); vars.prPortalEnter = (Func)(() => { return vars.splitByXYZ(-71f, -69f, -117f, -115f, 19.8f, 20.2f); }); vars.prPortalExit = (Func)(() => { return vars.splitByXYZ(-71f, -69f, -117f, -115f, 319.8f, 320.2f); }); vars.libraryV1 = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67116821, 67116816 }); }); vars.libraryV2 = (Func)(() => { return current.map == 67116821 && vars.oldX < -112 && current.xPos >= -112 && current.storyValue == 42; }); vars.hourglassRevisit = (Func)(() => { return vars.oldMap == 1006704427 && current.map == 1006704429 && current.storyValue == 45; }); vars.trPortalEnter = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { -1509855113, 1006704431 }); }); vars.trPortalExit = (Func)(() => { return vars.splitByXYZ(-53.5f, -51.5f, 113f, 114f, 117.8f, 118.2f); }); vars.maskOn = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 285231214 }); }); vars.scPortalEnter = (Func)(() => { return vars.splitByXYZ(-72f, -70f, 273f, 274f, 132.8f, 133.2f); }); vars.scPortalExit = (Func)(() => { return vars.splitByXYZ(-72f, -70f, 273f, 274f, 432.8f, 433.2f); }); vars.griffinV1 = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 285231574 }) && current.yPos < 195; }); vars.griffinV2 = (Func)(() => { return current.map == 285231574 && vars.oldY > 166.5 && current.yPos <= 166.5; }); vars.ugPortalEnter = (Func)(() => { return vars.splitByXYZ(78f, 80f, 107f, 108f, 412.3f, 412.7f); }); vars.ugPortalExit = (Func)(() => { return vars.splitByXYZ(78f, 80f, 107f, 108f, 112.3f, 112.7f); }); vars.mirroredFates = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 1006801611 }); }); vars.favorUnknown = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 135501700 }); }); vars.libraryRevisit = (Func)(() => { return current.map == 67116821 && vars.oldX < -112 && current.xPos >= -112 && current.storyValue == 60; }); vars.maskOff = (Func)(() => { return vars.splitCutsceneByMap(new HashSet { 67112526 }) && current.storyValue == 64; }); vars.CheckSplit = (Func)(key => { return (vars.CompletedSplits.Add(key) && settings[key]); }); } start { // Start the timer when a new game is started (after the opening cutscene has ended) return (current.map == 1292342859 && vars.oldCutscene == 1 && current.cutscene == 2); } onStart { // Refresh all splits when we start the run, none are yet completed vars.CompletedSplits.Clear(); } reset { // Reset the timer when a new game is started (when the first area of the boat loads) return (old.map == 234881388 && current.map == 1292342859); } update { // This is a work-around for the "old" state not working as expected in the init block vars.oldCutscene = old.cutscene; vars.oldState = old.state; vars.oldSecondary = old.secondaryWeapon; vars.oldStory = old.storyValue; vars.oldMap = old.map; vars.oldX = old.xPos; vars.oldY = old.yPos; vars.oldZ = old.zPos; List componentsToRemove = new List(); timer.Run.Metadata.SetCustomVariable("storyGate", current.storyValue.ToString()); timer.Run.Metadata.SetCustomVariable("chests", vars.getTrackerText(current.chestBits, 0x0003FFFFFFFFFFFF)); timer.Run.Metadata.SetCustomVariable("mainWeapons", vars.getTrackerText(current.weaponBits, 0x37C0000000000000)); timer.Run.Metadata.SetCustomVariable("swords", vars.getTrackerText(current.weaponBits, 0x0005FFFF00000000)); timer.Run.Metadata.SetCustomVariable("axes", vars.getTrackerText(current.weaponBits, 0x0002000000003FFE)); timer.Run.Metadata.SetCustomVariable("maces", vars.getTrackerText(current.weaponBits, 0x000000000FF00000)); timer.Run.Metadata.SetCustomVariable("daggers", vars.getTrackerText(current.weaponBits, 0x00000000000FC000)); timer.Run.Metadata.SetCustomVariable("secretWeapons", vars.getTrackerText(current.weaponBits, 0x00080000F0000000)); } split { foreach (var data in vars.splitsData) { if (data.Value.Item5() && vars.CheckSplit(data.Key)) { print(data.Key); return true; } } }