state("KINGDOM HEARTS FINAL MIX", "EG Global") // 1.0.0.10
{
    byte arch_behemoth_kills : 0x2DEA59A;
    bool black : 0x4DD3F8;
    byte8 collected_items_1 : 0x2DEA202;
    byte102 collected_items_2 : 0x2DEA291;  
    bool cutscene : 0x233F1F4;
    byte dest_behemoth_kills : 0x2DEA598;
    byte96 enemies_defeated : 0x2DEA53A;
    byte42 equips : 0x2DEA233;
    byte fightend : 0x2D54438;
    byte in_gummi : 0x50832D;
    bool load : 0x232E6E8;
    bool load_2 : 0x233F230;
    byte7 magic_level_flags : 0x2DEB97E;
    byte magic_unlock_val : 0x2DE9DD4;
    ushort mini_game_count : 0x2E9DD74;
    bool party_load : 0x2E1FE7C;
    bool paused : 0x232E9BC;
    byte33 power_wild_gummis : 0x2DF5BDC;
    ushort puppy_count : 0x2E9DB28;
    ushort reports : 0x2DEB720;
    ushort room : 0x2340EC4;
    ushort scene : 0x2340EC8;
    bool save_load : 0x2E20F38;
    byte sora_hp : 0x2D5D64C;
    uint sora_exp : 0x2DE9DA0;
    bool summon_load : 0x2D54D08;
    byte text_progress : 0x232E974;
    byte torn_page_count : 0x2DEB160;
    byte6 trinity_counts : 0x2DEB9C6;
    byte white : 0x234081C;
    ushort world : 0x2340ECC;
}

state("KINGDOM HEARTS FINAL MIX", "EG JP") // 1.0.0.10
{
    byte arch_behemoth_kills : 0x2DEA59A;
    bool black : 0x4DD3F8;
    byte8 collected_items_1 : 0x2DEA202;
    byte102 collected_items_2 : 0x2DEA291;  
    bool cutscene : 0x233F1F4;
    byte dest_behemoth_kills : 0x2DEA598;
    byte96 enemies_defeated : 0x2DEA53A;
    byte42 equips : 0x2DEA233;
    byte fightend : 0x2D54438;
    byte in_gummi : 0x50832D;
    bool load : 0x232E6E8;
    bool load_2 : 0x233F230;
    byte7 magic_level_flags : 0x2DEB97E;
    byte magic_unlock_val : 0x2DE9DD4;
    ushort mini_game_count : 0x2E9DD74;
    bool party_load : 0x2E1FE7C;
    bool paused : 0x232E9BC;
    byte33 power_wild_gummis : 0x2DF5BDC;
    ushort puppy_count : 0x2E9DB28;
    ushort reports : 0x2DEB720;
    ushort room : 0x2340EC4;
    ushort scene : 0x2340EC8;
    bool save_load : 0x2E20F38;
    byte sora_hp : 0x2D5D64C;
    uint sora_exp : 0x2DE9DA0;
    bool summon_load : 0x2D54D08;
    byte text_progress : 0x232E974;
    byte torn_page_count : 0x2DEB160;
    byte6 trinity_counts : 0x2DEB9C6;
    byte white : 0x234081C;
    ushort world : 0x2340ECC;
}

state("KINGDOM HEARTS FINAL MIX", "Steam Global") // 1.0.0.2
{
    byte arch_behemoth_kills : 0x2DE9B9A;
    bool black : 0x4DC718;
    byte8 collected_items_1 : 0x2DE9802;
    byte102 collected_items_2 : 0x2DE9891;  
    bool cutscene : 0x233E808;
    byte dest_behemoth_kills : 0x2DE9B98;
    byte96 enemies_defeated : 0x2DE9B3A;
    byte42 equips : 0x2DE9833;
    byte fightend : 0x2D53A38;
    byte in_gummi : 0x5075A8; // differs to cover a change on linux systems
    bool load : 0x232DCE8;
    bool load_2 : 0x233E830;
    byte7 magic_level_flags : 0x2DEAF7E;
    byte magic_unlock_val : 0x2DE93D4;
    ushort mini_game_count : 0x2E9D394;
    bool party_load : 0x2E1F4E8;
    bool paused : 0x232DFC0;
    byte33 power_wild_gummis : 0x2DF51DC;
    ushort puppy_count : 0x2E9D148;
    ushort reports : 0x2DEAD20;
    ushort room : 0x233FE8C;
    ushort scene : 0x233FE90;
    bool save_load : 0x2E20564;
    byte sora_hp : 0x2D5CC4C;
    uint sora_exp : 0x2DE93A0;
    bool summon_load : 0x2D54308;
    byte text_progress : 0x232DF74;
    byte torn_page_count : 0x2DEA760;
    byte6 trinity_counts : 0x2DEAFC6;
    byte white : 0x233FE1C;
    ushort world : 0x233FE94;
}

state("KINGDOM HEARTS FINAL MIX", "Steam JP") // 1.0.0.2
{
    byte arch_behemoth_kills : 0x2DE9B9A;
    bool black : 0x4DC718;
    byte8 collected_items_1 : 0x2DE9802;
    byte102 collected_items_2 : 0x2DE9891;  
    bool cutscene : 0x233E808;
    byte dest_behemoth_kills : 0x2DE9B98;
    byte96 enemies_defeated : 0x2DE9B3A;
    byte42 equips : 0x2DE9833;
    byte fightend : 0x2D53A38;
    byte in_gummi : 0x5075A8; // differs to cover a change on linux systems
    bool load : 0x232DCE8;
    bool load_2 : 0x233E830;
    byte7 magic_level_flags : 0x2DEAF7E;
    byte magic_unlock_val : 0x2DE93D4;
    ushort mini_game_count : 0x2E9D394;
    bool party_load : 0x2E1F4E8;
    bool paused : 0x232DFC0;
    byte33 power_wild_gummis : 0x2DF51DC;
    ushort puppy_count : 0x2E9D148;
    ushort reports : 0x2DEAD20;
    ushort room : 0x233FE8C;
    ushort scene : 0x233FE90;
    bool save_load : 0x2E20564;
    byte sora_hp : 0x2D5CC4C;
    uint sora_exp : 0x2DE93A0;
    bool summon_load : 0x2D54308;
    byte text_progress : 0x232DF74;
    byte torn_page_count : 0x2DEA760;
    byte6 trinity_counts : 0x2DEAFC6;
    byte white : 0x233FE1C;
    ushort world : 0x233FE94;
}

startup
{
    vars.booting = false;
    vars.summon_timer = 0;

    settings.Add("main", true, "End of section splits");
        settings.Add("ds1", true, "Darkside 1", "main");
        settings.Add("ds2", true, "Darkside 2", "main");
        settings.Add("guard", true, "Guard Armor", "main");
        settings.Add("tm", true, "Trick Master", "main");
        settings.Add("clayton_2", true, "Clayton 2", "main");
        settings.Add("gj", true, "Genie Jafar", "main");
        settings.Add("pc2", true, "Parasite Cage 2", "main");
        settings.Add("oogie_manor", true, "Oogie Manor", "main");
        settings.Add("hook", true, "Captain Hook", "main");
        settings.Add("oppo", true, "Opposite Armor", "main");
        settings.Add("riku2", true, "Riku 2", "main");
        settings.Add("behemoth", true, "Behemoth", "main");
        settings.Add("cher", true, "Chernabog", "main");
        settings.Add("a2", true, "Ansem 2", "main");

    settings.Add("optional_splits", true, "All other Any % splits");
        settings.Add("shadows_1", false, "Shadows 1 (first full group)", "optional_splits");
        settings.Add("shadows_2", false, "Shadows 2 (post save point cutscene)", "optional_splits");
        settings.Add("day_1", false, "Destiny Islands Day One", "optional_splits");
        settings.Add("destiny", false, "Destiny Islands Day Two (on raft supplies claimed)", "optional_splits");
        settings.Add("destiny_opt", false, "Destiny Islands Day Two (on transition)", "optional_splits");
        settings.Add("leon", true, "Leon", "optional_splits");
        settings.Add("crank", true, "Crank Tower - Fight End", "optional_splits");
        settings.Add("crank_alt", false, "Crank Tower - Post Fight Cutscene", "optional_splits");
        settings.Add("sabor_1", true, "Sabor 1", "optional_splits");
        settings.Add("power_wilds", false, "Split after Power Wilds", "optional_splits");
        settings.Add("sabor_2", true, "Sabor 2", "optional_splits");
        settings.Add("clayton_1", false, "Clayton 1", "optional_splits");
        settings.Add("wfc", false, "Waterfall Cavern", "optional_splits");
        settings.Add("tt_2", false, "Traverse Town 2", "optional_splits");
        settings.Add("save_al", false, "Save Aladdin", "optional_splits");
        settings.Add("pot", true, "Pot Centipede", "optional_splits");
        settings.Add("tiger", true, "Tiger Head", "optional_splits");
        settings.Add("jafar", true, "Jafar", "optional_splits");
        settings.Add("carpet_escape", false, "Carpet Escape", "optional_splits");
        settings.Add("pc", true, "Parasite Cage 1", "optional_splits");
        settings.Add("fmn", false, "Forget Me Not", "optional_splits");
        settings.Add("jb", false, "Jack in the Box", "optional_splits");
        settings.Add("lsb", true, "LSB", "optional_splits");
        settings.Add("oogie", true, "Oogie Boogie", "optional_splits");
        settings.Add("ship_early", false, "Hooks Ship (in gummi mission)", "optional_splits");
        settings.Add("ship", false, "Hooks Ship (at first cutscene in world)", "optional_splits");
        settings.Add("anti", true, "Anti Sora", "optional_splits");
        settings.Add("pre_hook", false, "Pre Hook", "optional_splits");
        settings.Add("fake_guard", false, "Fake Guard Armor", "optional_splits");
        settings.Add("riku", true, "Riku 1", "optional_splits");
        settings.Add("emblem", false, "Emblem Door", "optional_splits");
        settings.Add("dumbo_1", false, "Dumbo Skip 1", "optional_splits");
        settings.Add("mal", true, "Maleficent", "optional_splits");
        settings.Add("dragon", true, "Dragon Maleficent", "optional_splits");
        settings.Add("tt_4", false, "Traverse Town 4", "optional_splits");
        settings.Add("dumbo_2", false, "Dumbo Skip 2", "optional_splits");
        settings.Add("dumbo_3", false, "Dumbo Skip 3", "optional_splits");
        settings.Add("arch", false, "Arch Behemoth", "optional_splits");
        settings.Add("oc_portal", false, "Olympus Coliseum portal", "optional_splits");
        settings.Add("atl_portal", false, "Atlantica portal", "optional_splits");
        settings.Add("hbp", false, "Hollow Bastion portal", "optional_splits");
        settings.Add("behemoth_3", false, "Behemoth 3 (final rest)", "optional_splits");
        settings.Add("final_rest", true, "Enter Final Rest", "optional_splits");
        settings.Add("a1", true, "Ansem 1", "optional_splits");
        settings.Add("ds3", true, "Dark Side 3", "optional_splits");
        settings.Add("a3", true, "Ansem 3", "optional_splits");
        settings.Add("sc", true, "Shadow Core", "optional_splits");
        settings.Add("artillery", false, "Artillery", "optional_splits");
        settings.Add("dbc", true, "Dark Ball Core", "optional_splits");
        settings.Add("face", true, "Face", "optional_splits");
        settings.Add("invc", true, "Invisible Core", "optional_splits");
        settings.Add("mc", true, "Main Core", "optional_splits");

    settings.Add("all_worlds_splits", false, "All Worlds categories");
        settings.Add("thunder", false, "Thunder", "all_worlds_splits");
        settings.Add("power_boost", false, "100 Acre Wood Power Boost", "all_worlds_splits");
        settings.Add("torn_page_1", false, "Torn Page 1 Complete", "all_worlds_splits");
        settings.Add("torn_page_2", false, "Torn Page 2 Complete", "all_worlds_splits");
        settings.Add("torn_page_3", false, "Torn Page 3 Complete", "all_worlds_splits");
        settings.Add("torn_page_4", false, "Torn Page 4 Complete", "all_worlds_splits");
        settings.Add("torn_page_5", false, "Torn Page 5 Complete", "all_worlds_splits");
        settings.Add("seal_100_aw", false, "100 Acre Wood", "all_worlds_splits");
        settings.Add("cloud_1", false, "Cloud 1", "all_worlds_splits");
        settings.Add("cerb_1", false, "Cerberus 1", "all_worlds_splits");
        settings.Add("cloud_2", false, "Cloud 2", "all_worlds_splits");
        settings.Add("herc_cup", false, "Hercules Cup", "all_worlds_splits");
        settings.Add("atl_dock", false, "Atlantica Dock", "all_worlds_splits");
        settings.Add("urs_1", false, "Ursula 1", "all_worlds_splits");
        settings.Add("urs_2", false, "Ursula 2", "all_worlds_splits");

    settings.Add("jj_splits", false, "Jimminy's Journal categories");
        settings.Add("hb_2", false, "Behemoth + Library Clean Up", "jj_splits");
        settings.Add("atlantica_1", false, "Atlantica 1 (torn page)", "jj_splits");
        settings.Add("phil_cup", false, "Phil Cup", "jj_splits");
        settings.Add("phil_cup_solo", false, "Phil Cup (solo)", "jj_splits");
        settings.Add("pg_cup", false, "Pegasus Cup", "jj_splits");
        settings.Add("hades_seed_49", false, "Hades Cup Seed 49 -> 40", "jj_splits");
        settings.Add("hades_seed_39", false, "Hades Cup Seed 39 -> 30", "jj_splits");
        settings.Add("hades_seed_29", false, "Hades Cup Seed 29 -> 20", "jj_splits");
        settings.Add("hades_seed_19", false, "Hades Cup Seed 19 -> 10", "jj_splits");
        settings.Add("hades_seed_9", false, "Hades Cup Seed 9 -> End", "jj_splits");
        settings.Add("ice_titan", false, "Ice Titan", "jj_splits");
        settings.Add("seph", false, "Sephiroth", "jj_splits");
        settings.Add("kurt", false, "Kurt Zisa", "jj_splits");
        settings.Add("nap_time", false, "Phantom", "jj_splits");
        settings.Add("xemnas", false, "Unknown", "jj_splits");
        // If a split breaks/a reroute happens update the dictionary in the init for the sepcific world and difficulty
        settings.Add("revisit_jj_check", false, "Revists checking Journal collection (breakable by reroute)", "jj_splits");
            settings.Add("wl_2", false, "Wonderland Revisit", "revisit_jj_check");
            settings.Add("dj_2", false, "Deep Jungle Revisit", "revisit_jj_check");
            settings.Add("ag_2", false, "Agrabah Revisit", "revisit_jj_check");
            settings.Add("mo_2", false, "Monstro Revisit", "revisit_jj_check");
            settings.Add("ht_2", false, "Halloween Town Revisit", "revisit_jj_check");
            settings.Add("nl_2", false, "Neverland Revisit", "revisit_jj_check");
            settings.Add("eow", false, "End of the World 1", "revisit_jj_check");
            settings.SetToolTip(
                "eow",
                "Split when returning to gummi map from end of world."
            );
            settings.Add("jj_complete", false, "Journal Complete - Enter Final Fights", "revisit_jj_check");
            settings.Add("jj_complete_early", false, "Journal Complete - Check", "revisit_jj_check");

    settings.Add("plat_splits", false, "Plat trophy RTA");
        settings.Add("gummi_kills", false, "2.5k Gummi Kills", "plat_splits");
        settings.Add("each_mat", false, "1 Each Rare Synth", "plat_splits");
        settings.SetToolTip(
            "each_mat",
            "Split after collecting one of each rare synthasis material."
        );
        settings.Add("tt_final", false, "Traverse Town Final", "plat_splits");
        settings.SetToolTip(
            "tt_final",
            "Split when exiting Traverse Town with Ultima Weapon and Aeroga."
        );
        settings.Add("more", false, "More to come!", "plat_splits");


    settings.Add("misc", false, "misc catagories");
        settings.Add("coco", false, "99 coconut", "misc");
            settings.Add("per_10", false, "Every 10 (and final 9)", "coco");
            settings.Add("per_1", false, "Every nut", "coco");
        settings.Add("boss_rush", false, "Boss Rush", "misc");
            settings.Add("custom_install", false, "Custom game install location", "boss_rush");
            settings.SetToolTip(
                "custom_install",
                "Check this and update the path in the asl file if you have the game installed in a non standard location for use with the boss rush!"
            );

    settings.Add("settings", false, "Settings");
        settings.Add("re-split", false, "Re split", "settings");
            settings.SetToolTip(
                "re-split",
                "When set, splits will trigger more than once if a death occurs." +
                "\nFor example if you die to Ansem 2, Darkside 3 will split again."
            );
}

start
{
    // resets all used variables on restart
    vars.completed_splits = new HashSet<string>();

    // traverse town vars
    vars.fake_guard = false;
    vars.oppo = false;
    vars.aero_level_up = false;

    // wonderland vars
    vars.wl_puppies = 0;

    // deep jungle vars
    vars.pw_gummis = 0;
    vars.clayton_1 = false;
    vars.clayton_2 = false;
    vars.dj_puppies = 0;

    // agrabah vars
    vars.ag_puppies = 0;

    // atlantica vars
    vars.atl_torn_page = false;

    // halloween town vars
    vars.ht_puppies = 0;

    // olympus coliseum vars
    vars.cloud_2 = false;
    vars.herc_cup = false;
    vars.next_ability_slot_idx = 0;

    // monstro vars
    vars.mo_torn_page = false;
    vars.mo_puppies = 0;

    // neverland vars
    vars.nl_puppies = 0;
    vars.pre_hook = false;

    // end of world vars
    vars.journal_complete = false;
    vars.behemoth_3 = false;
    vars.ds3 = false;

    // outside world vars
    vars.world_puppies_complete = false;
    vars.world_enemies_complete = false;
    vars.world_trinities_complete = false;
    vars.world_mini_game_complete = false;
    vars.gummi_kills = 0;

    // misc category vars
    vars.finished_nut = false;

    // manual back step vars
    vars.back_split = "";

    var ng = vars.watchers["newgame"];
    ng.Update(game);
    if (settings["boss_rush"]) {
        var drives = "CDEFGHIJKLMNOPQRSTUVWXYZ";
        var base_path = @":\Program Files\Epic Games\KH_1.5_2.5";
        if (settings["custom_install"]) {
            base_path = @":\Users\chuds\Desktop\KH Current\KH_1.5_2.5";
        }
        foreach (char drive in drives) {
            if (Directory.Exists(drive + base_path)) {
                vars.autosavedst = drive + base_path + @"\autosave.dat";
                break;
            } 
        }
        File.Copy(@"Boss Rush\001_Darkside 1.dat", vars.autosavedst, true);
    } else {
        return ng.Current == 7 && ng.Old == 6;
    }
}

split
{
    int current_world = current.world;
    int old_world = old.world;
    var output_catch = "";
    var eow_scene = vars.watchers["eow_scene"];
    var gummi_start_world = vars.watchers["gummi_start_world"];
    var gummi_destination_world = vars.watchers["gummi_destination_world"];
    // Only works for certain fights, current use is for leon and sabor 1
    bool fight_exp = current.sora_exp > old.sora_exp && current.sora_exp - old.sora_exp > 5;
    bool fight_complete = current.fightend == 2 && old.fightend == 0;
    bool death = current.sora_hp == 0 && old.sora_hp > 0;
    vars.summon_timer = current.summon_load ? vars.summon_timer + (current.paused ? 0 : 1) : 0;

    // Final fight split always goes
    if (fight_complete && current_world == 16 && current.room == 33 && current.scene == 4) {
        if (settings["boss_rush"]) {
            File.Copy(@"Boss Rush\001_Darkside 1.dat", vars.autosavedst, true);
        }
        return true;
    }

    if (settings["main"]) {
        if (death) {
            // death abuse splits
            if (current_world == 0 && current.room == 4) {
                if (settings["boss_rush"]) {
                    File.Copy(@"Boss Rush\002_Darkside 2.dat", vars.autosavedst, true);
                }
                return settings["ds1"];
            }
        }
        if (fight_complete) {
            // fight win splits
            switch (current_world) {
                // station of awakening
                case 0:
                    if (current.room == 4) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\002_Darkside 2.dat", vars.autosavedst, true);
                        }
                        return settings["ds1"];
                    }
                    break;
                // destiny islands
                case 1:
                    if (current.room == 8) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\003_Leon.dat", vars.autosavedst, true);
                        }
                        return settings["ds2"];
                    }
                    break;
                // traverse town
                case 3:
                    if (current.room == 2) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\005_Crank Tower.dat", vars.autosavedst, true);
                        }
                        return settings["guard"];
                    }
                    if (current.room == 1) {
                        if (!settings["optional_splits"] && !vars.fake_guard) {
                            vars.back_split = "fake";
                            vars.fake_guard = true;
                            return false;
                        }
                        if (vars.fake_guard) {
                            vars.back_split = "";
                            if (settings["boss_rush"]) {
                                File.Copy(@"Boss Rush\021_Riku 1.dat", vars.autosavedst, true);
                            }
                            return settings["oppo"];
                        }
                    }
                    break;
                // wonderland
                case 4:
                    if (current.room == 1) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\007_Sabor 2.dat", vars.autosavedst, true);
                        }
                        return settings["tm"];
                    }
                    break;
                // deep jungle
                case 5:
                    if (current.room == 11) {
                        if (!settings["optional_splits"] && !vars.clayton_1) {
                            vars.back_split = "clay1";
                            vars.clayton_1 = true;
                            return false;
                        }
                        if (vars.clayton_1) {
                            vars.back_split = "";
                            if (settings["boss_rush"]) {
                                File.Copy(@"Boss Rush\009_Pot Centipede.dat", vars.autosavedst, true);
                            }
                            return settings["clayton_2"];
                        }
                    }
                    break;
                // agrabah
                case 8:
                    if (current.room == 17) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\013_Parasite Cage 1.dat", vars.autosavedst, true);
                        }
                        return settings["gj"];
                    }
                    break;
                // halloween town
                case 10:
                    if (current.room == 8) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\018_Anti Sora.dat", vars.autosavedst, true);
                        }
                        return settings["oogie_manor"];
                    }
                    break;
                // monstro
                case 12:
                    if (current.room == 2) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\015_Lock Shock Barrel.dat", vars.autosavedst, true);
                        }
                        return settings["pc2"];
                    }
                    break;
                // neverland
                case 13:
                    if (current.room == 8) {
                        vars.back_split = "";
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\020_Opposite Armor.dat", vars.autosavedst, true);
                        }
                        return settings["hook"];
                    }
                    break;
                // hollow bastion
                case 15:
                    if (current.room == 14) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\025_Behemoth.dat", vars.autosavedst, true);
                        }
                        return settings["riku2"];
                    }
                    if (current.room == 15) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\026_Arch Behemoth.dat", vars.autosavedst, true);
                        }
                        return settings["behemoth"];
                    }
                    break;
                // end of world
                case 16:
                    if (current.room == 26) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\028_Ansem 1.dat", vars.autosavedst, true);
                        }
                        return settings["cher"];
                    }
                    eow_scene.Update(game); 
                    if (current.room == 30 && eow_scene.Current == 257) {
                        if (!settings["optional_splits"]) {
                            if (!vars.ds3) {
                                vars.back_split = "ds3";
                                vars.ds3 = true;
                                return false;
                            }
                        }
                        if (vars.ds3) {
                            vars.back_split = "";
                            if (settings["boss_rush"]) {
                                File.Copy(@"Boss Rush\030_Ansem 3.dat", vars.autosavedst, true);
                            }
                            return settings["a2"];
                        }
                    }
                    break;
            }
        }
    }

    if (settings["optional_splits"]) {
        // fight win splits
        if (fight_complete) {
            switch (current_world) {
                // traverse town
                case 3:
                    if (current.room == 0 && current.scene == 3) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\004_Guard Armor.dat", vars.autosavedst, true);
                        }
                        return vars.completed_splits.Add("leon") && settings["leon"];
                    }
                    if (current.room == 1 && !vars.fake_guard) {
                        vars.back_split = "fake";
                        vars.fake_guard = true;
                        return settings["fake_guard"];
                    }
                    break;
                // wonderland
                case 4:
                    if (current.room == 3) {
                        vars.completed_splits.Add("crank");
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\006_Trickmaster.dat", vars.autosavedst, true);
                        }
                        return settings["crank"];
                    }
                    break;
                // deep jungle
                case 5:
                    if (current.room == 0 && current.scene == 0) {
                        return vars.completed_splits.Add("sabor_1") && settings["sabor_1"];
                    }
                    if (current.room == 2) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\008_Clayton.dat", vars.autosavedst, true);
                        }
                        return settings["sabor_2"];
                    }
                    if (current.room == 11 && !vars.clayton_1) {
                        vars.back_split = "clay1";
                        vars.clayton_1 = true;
                        return settings["clayton_1"];
                    }
                    break;
                // agrabah splits
                case 8:
                    if (current.room == 19) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\010_Tiger Head.dat", vars.autosavedst, true);
                        }
                        return settings["pot"];
                    }
                    if (current.room == 1) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\011_Jafar.dat", vars.autosavedst, true);
                        }
                        return settings["tiger"];
                    }
                    if (current.room == 16) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\012_Genie Jafar.dat", vars.autosavedst, true);
                        }
                        return settings["jafar"];
                    }
                    break;
                // halloween town
                case 10:
                    if (current.room == 9) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\016_Oogie Boogie.dat", vars.autosavedst, true);
                        }
                        return settings["lsb"];
                    }
                    if (current.room == 7) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\017_Oogie Manor.dat", vars.autosavedst, true);
                        }
                        return settings["oogie"];
                    }
                    break;
                // monstro
                case 12:
                    if (current.room == 4) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\014_Parasite Cage 2.dat", vars.autosavedst, true);
                        }
                        return settings["pc"];
                    }
                    break;
                // neverland
                case 13:
                    if (current.room == 6) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\019_Hook.dat", vars.autosavedst, true);
                        }
                        return settings["anti"];
                    }
                    if (vars.pre_hook && !vars.hook && !settings["hook"] && current.room == 8) {
                        vars.back_split = "";
                        vars.hook = true;
                    }
                    break;
                // hollow bastion
                case 15:
                    if (current.room == 4) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\022_Maleficent.dat", vars.autosavedst, true);
                        }
                        return settings["riku"];
                    }
                    if (current.room == 11) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\023_Dragon Maleficent.dat", vars.autosavedst, true);
                        }
                        return settings["mal"];
                    }
                    if (current.room == 12 && current.scene == 0) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\024_Riku Ansem.dat", vars.autosavedst, true);
                        }
                        return settings["dragon"];
                    }
                    break;
                // end of world
                case 16:
                    eow_scene.Update(game); 
                    if (current.room == 30 && eow_scene.Current == 256) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\029_Ansem 2.dat", vars.autosavedst, true);
                        }
                        return settings["a1"];
                    }
                    if (!vars.ds3 && current.room == 30) {
                        vars.ds3 = true;
                        vars.back_split = "ds3";
                        return settings["ds3"];
                    }
                    if (current.room == 33) {
                        if (current.scene == 0) {
                            if (settings["boss_rush"]) {
                                File.Copy(@"Boss Rush\031_World of Chaos Face.dat", vars.autosavedst, true);
                            }
                            return settings["a3"];
                        }
                        if (current.scene == 2) {
                            if (settings["boss_rush"]) {
                                File.Copy(@"Boss Rush\032_Ansem 4.dat", vars.autosavedst, true);
                            }
                            return settings["face"];
                        }
                        if (current.scene == 3) {
                            return settings["mc"];
                        }
                    }
                    if (current.room == 36) {
                        return settings["sc"];
                    }
                    if (current.room == 37) {
                        return settings["dbc"];
                    }
                    if (current.room == 38) {
                        return settings["invc"];
                    }
                    break;
            }
        } else {
            // all other splits
            switch (current_world) {
                // station of awakening
                case 0:
                    if (current.enemies_defeated[0] >= 5 && current.cutscene) {
                        return vars.completed_splits.Add("shadows_1") && settings["shadows_1"];
                    }
                    // shadows killed
                    if (current.enemies_defeated[0] >= 9 && current.text_progress > 0 && old.text_progress == 0) {
                        return vars.completed_splits.Add("shadows_2") && settings["shadows_2"];
                    }
                    break;
                // destiny islands
                case 1:
                    // logs 
                    if (current.collected_items_2[40] < old.collected_items_2[40]) {
                        return settings["day_1"];
                    }
                    // coconuts
                    if (current.collected_items_2[46] < old.collected_items_2[46]) {
                        return settings["destiny"];
                    }
                    if (old.room == 2 && current.room == 3 && current.scene == 2){
                        return vars.completed_splits.Add("destiny_opt") && settings["destiny_opt"];                        
                    }
                    break;
                // traverse town
                case 3:
                    if (current.room == 0 && current.scene == 3 && ((death) || (fight_exp))) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\004_Guard Armor.dat", vars.autosavedst, true);
                        }
                        return vars.completed_splits.Add("leon") && settings["leon"];
                    }
                    if (current.room == 10 && current.scene == 11 && current.in_gummi > 0) {
                        return vars.completed_splits.Add("tt_2") && settings["tt_2"];
                    }
                    // oath keeper
                    if (current.scene == 0 && current.room == 10 && current.in_gummi > 0 && current.equips[38] == 1) {
                        return vars.completed_splits.Add("tt_4") && settings["tt_4"];
                    }
                    break;
                // wonderland
                case 4:
                    if (current.room == 3 && vars.completed_splits.TryGetValue("crank", out output_catch) && current.cutscene) {
                        return vars.completed_splits.Add("crank_alt") && settings["crank_alt"];
                    }
                    break;
                // deep jungle
                case 5:
                    if (current.room == 0 && current.scene == 0 && ((death) || (fight_exp))) {
                        return vars.completed_splits.Add("sabor_1") && settings["sabor_1"];
                    }
                    if (
                        // house gummi
                        (current.room == 0 && current.scene == 3 && current.power_wild_gummis[13] != old.power_wild_gummis[13]) ||
                        // bamboo gummi
                        (current.room == 2 && current.scene == 2 && current.power_wild_gummis[0] != old.power_wild_gummis[0]) ||
                        // climbing trees gummi
                        (current.room == 6 && current.scene == 2 && current.power_wild_gummis[32] != old.power_wild_gummis[32]) ||
                        // cliff gummi
                        (current.room == 11 && current.scene == 2 && current.power_wild_gummis[31] != old.power_wild_gummis[31]) ||
                        // camp gummi
                        (current.room == 12 && current.scene == 1 && current.power_wild_gummis[7] != old.power_wild_gummis[7])
                    ) {
                        vars.pw_gummis += 1;
                    }
                    if (vars.pw_gummis == 5) {
                        vars.pw_gummis = 0;
                        return vars.completed_splits.Add("power_wilds") && settings["power_wilds"];
                    }
                    if (current.room == 10 && current.scene == 0) {
                        return vars.completed_splits.Add("wfc") && settings["wfc"];
                    }
                    break;
                // agrabah
                case 8:
                    if (current.room == 0 && current.scene == 4) {
                        return vars.completed_splits.Add("save_al") && settings["save_al"];
                    }
                    if (current.room == 1 && current.scene == 4) {
                        return vars.completed_splits.Add("carpet_escape") && settings["carpet_escape"];
                    }
                    break;
                // halloween town
                case 10:
                    // forget me not
                    if (current.room == 10 && current.collected_items_2[75] == 0 && old.collected_items_2[75] == 1) {
                        return settings["fmn"];
                    }
                    // jack in the box
                    if (current.room == 10 && current.collected_items_2[76] == 0 && old.collected_items_2[76] == 1) {
                        return settings["jb"];
                    }
                    break;
                // neverland
                case 13:
                    var neverland_scene = vars.watchers["neverland_scene"];
                    neverland_scene.Update(game);
                    if (!vars.pre_hook && current.room == 8 && current.scene == 1 && neverland_scene.Current == 80) {
                        vars.back_split = "pre_hook";
                        vars.pre_hook = true;
                        return settings["pre_hook"];
                    }
                    if (current.cutscene && gummi_destination_world.Current == 13 && (gummi_start_world.Current == 10 || gummi_start_world.Current == 9)) {
                        return vars.completed_splits.Add("ship") && settings["ship"];
                    }
                    break;
                // hollow bastion
                case 15:
                    if (old.room == 11 && current.room == 4 && current.scene == 13) {
                        return settings["emblem"];
                    }
                    if (current.room == 3 && current.scene == 13 && current.summon_load && vars.summon_timer > 30) {
                        return vars.completed_splits.Add("dumbo_1") && settings["dumbo_1"];
                    }
                    if (current.room == 1 && current.scene == 14 && current.summon_load && vars.summon_timer > 30) {
                        return vars.completed_splits.Add("dumbo_2") && settings["dumbo_2"];
                    }
                    if (current.room == 3 && current.scene == 14 && current.summon_load && vars.summon_timer > 30) {
                        return vars.completed_splits.Add("dumbo_3") && settings["dumbo_3"];
                    }
                    break;
                // end of world
                case 16:

                    if (current.room == 12 && current.scene == 13 && current.arch_behemoth_kills > old.arch_behemoth_kills) {
                        if (settings["boss_rush"]) {
                            File.Copy(@"Boss Rush\027_Chernabog.dat", vars.autosavedst, true);
                        }
                        return settings["arch"];
                    }
                    if (old.room == 18 && current.room == 15) {
                        return vars.completed_splits.Add("oc_portal") && settings["oc_portal"];
                    }
                    if (old.room == 21 && current.room == 15) {
                        return vars.completed_splits.Add("atl_portal") && settings["atl_portal"];
                    }
                    if (old.room == 25 && current.room == 15) {
                        return settings["hbp"];
                    }
                    if (!vars.behemoth_3 && current.room == 28 && current.arch_behemoth_kills > old.arch_behemoth_kills) {
                        vars.behemoth_3 = true;
                        vars.back_split = "be3";
                        return settings["behemoth_3"];
                    }
                    if (current.room == 29 && !vars.completed_splits.TryGetValue("final_rest", out output_catch)) {
                        vars.back_split = "";
                        return vars.completed_splits.Add("final_rest") && settings["final_rest"];
                    }
                    if (old.room == 33 && current.room == 37) {
                        return settings["artillery"];
                    }
                    break;
            }
        }
        
        var ship = vars.watchers["hook_ship_flag"];
        ship.Update(game);
        if (gummi_destination_world.Current == 13 && ship.Current == 37 && (gummi_start_world.Current == 10 || gummi_start_world.Current == 9)) {
            return vars.completed_splits.Add("ship_early") && settings["ship_early"];
        }
    }

    if (settings["all_worlds_splits"]) {
        if (death) {
            // death abuse splits
            if (current_world == 11 && current.room == 2 && current.scene == 0) {
                return settings["cloud_1"];
            }
        }
        if (fight_complete) {
            // fight win splits
            switch (current_world) {
                // atlantica
                case 9:
                    if (current.room == 12 && current.scene == 2) {
                        return settings["urs_1"];
                    }
                    if (current.room == 16) {
                        return settings["urs_2"];
                    }
                    break;
                // olympus coliseum
                case 11:
                    if (current.room == 2 && current.scene == 0) {
                        return settings["cloud_1"];
                    }
                    if (current.room == 2 && current.scene == 1) {
                        return settings["cerb_1"];
                    }
                    if (current.room == 2 && current.scene == 9) {
                        if (!vars.cloud_2) {
                            vars.back_split = "cloud2";
                            vars.cloud_2 = true;
                            return settings["cloud_2"];
                        } else if (!vars.herc_cup) {
                            vars.herc_cup = true;
                            vars.back_split = "";
                            return settings["herc_cup"];
                        }
                    }
                    break;
            }
        } else {
            // all other splits
            switch (current_world) {
                // traverse town
                case 3:
                    if (old_world == 6 && vars.completed_splits.TryGetValue("torn_page_power", out output_catch)) {
                        return vars.completed_splits.Add("power_boost") && settings["power_boost"];
                    }
                    if (vars.completed_splits.TryGetValue("torn_page_5", out output_catch)) {
                        return vars.completed_splits.Add("seal_100_aw") && settings["seal_100_aw"];
                    }
                    break;
                // 100 acre wood
                case 6:
                    // power boost
                    if (current.collected_items_2[0] > old.collected_items_2[0]) {
                        vars.completed_splits.Add("torn_page_power");
                    }
                    // torn page 1 consumed
                    if (current.collected_items_2[60] == 0 && old.collected_items_2[60] == 1) {
                        return settings["torn_page_1"];
                    }
                    // torn page 2 consumed
                    if (current.collected_items_2[61] == 0 && old.collected_items_2[61] == 1) {
                        return vars.completed_splits.Add("torn_page_2") && settings["torn_page_2"];
                    }
                    // torn page 3 consumed
                    if (current.collected_items_2[62] == 0 && old.collected_items_2[62] == 1) {
                        return settings["torn_page_3"];
                    }
                    // torn page 4 consumed
                    if (current.collected_items_2[63] == 0 && old.collected_items_2[63] == 1) {
                        return vars.completed_splits.Add("torn_page_4") && settings["torn_page_4"];
                    }
                    // torn page 5 consumed
                    if (current.collected_items_2[64] == 0 && old.collected_items_2[64] == 1) {
                        return vars.completed_splits.Add("torn_page_5") && settings["torn_page_5"];
                    }
                    break;
                // atlantica
                case 9:
                    var docked_world = vars.watchers["docked_world"];
                    docked_world.Update(game);
                    if (docked_world.Current == 9) {
                        return vars.completed_splits.Add("atl_dock") && settings["atl_dock"];
                    }
                    break;
                // olympus coliseum
                case 11:
                    // thunder unlocked
                    if (current.in_gummi > 0 && (
                        current.magic_unlock_val == 5 ||
                        current.magic_unlock_val == 7 ||
                        current.magic_unlock_val == 15
                    )) {
                        return vars.completed_splits.Add("thunder") && settings["thunder"];
                    }
                    break;
            }
        }
    }

    if (settings["jj_splits"]) {
        if (fight_complete) {
            // fight win splits
            switch (current_world) {
                // agrabah
                case 8:
                    if (current.room == 0 && current.scene == 13) {
                        return settings["kurt"];
                    }
                    break;
                // olympus coliseum
                case 11:
                    if (current.room == 5 && current.scene == 0) {
                        return settings["pg_cup"];
                    }
                    if (current.room == 2 && current.scene == 11) {
                        return settings["hades_seed_39"];
                    }
                    if (current.room == 6 && current.scene == 4) {
                        return settings["hades_seed_19"];
                    }
                    if (current.room == 5 && current.scene == 13) {
                        return settings["hades_seed_9"];
                    }
                    if (current.room == 6 && current.scene == 5) {
                        return vars.completed_splits.Add("ice_titan") && settings["ice_titan"];
                    }
                    if (current.room == 6 && current.scene == 6) {
                        return vars.completed_splits.Add("seph") && settings["seph"];
                    }
                    break;
                // neverland
                case 13:
                    if (current.room == 9 && current.scene == 1) {
                        return vars.completed_splits.Add("nap_time") && settings["nap_time"];
                    }
                    break;
            }
        } else {
            // all other splits
            switch (current_world) {
                // wonderland
                case 4:
                    if (settings["wl_2"] && !vars.completed_splits.TryGetValue("wl_2", out output_catch)) {
                        if (
                            vars.wl_puppies < 4 &&
                            (
                                (current.room == 3 && vars.check_world_puppies(current_world, new int[] {2}, 1)) ||
                                (current.room == 9 && vars.check_world_puppies(current_world, new int[] {8}, 3)) ||
                                (current.room == 4 && vars.check_world_puppies(current_world, new int[] {1, 4}, 2))
                            )
                        ) {
                            vars.wl_puppies += 1;
                        }
                        // gigas shadow
                        if (vars.wl_puppies == 4 && current.enemies_defeated[82] >= 1) {
                            var wl_trinities = vars.watchers["wl_trinities"];
                            wl_trinities.Update(game);
                            if (current.in_gummi > 0 && wl_trinities.Current == 248) {
                                vars.wl_puppies = 5;
                                return vars.completed_splits.Add("wl_2");
                            }
                        }
                    }
                    break;
                // deep jungle
                case 5:
                    if (settings["dj_2"] && !vars.completed_splits.TryGetValue("dj_2", out output_catch)) {
                        if (
                            vars.dj_puppies < 4 &&
                            (
                                (current.room == 5 && vars.check_world_puppies(current_world, new int[] {1}, 1)) ||
                                (current.room == 4 && vars.check_world_puppies(current_world, new int[] {2}, 2)) ||
                                (current.room == 12 && vars.check_world_puppies(current_world, new int[] {4}, 3)) ||
                                (current.room == 9 && vars.check_world_puppies(current_world, new int[] {2}, 4))
                            )
                        ) {
                            vars.dj_puppies += 1;
                        }
                        // black ballad and bouncy wild
                        if (vars.dj_puppies == 4 && current.enemies_defeated[86] >= 1 && current.enemies_defeated[4] >= 1) {
                            var dj_trinities = vars.watchers["dj_trinities"];
                            var slider_journal_entry = vars.watchers["slider_journal_entry"];
                            dj_trinities.Update(game);
                            slider_journal_entry.Update(game);
                            if (current.in_gummi > 0  && dj_trinities.Current == 184 && slider_journal_entry.Current == 66) {
                                vars.dj_puppies = 5;
                                return vars.completed_splits.Add("dj_2");
                            }
                        }
                    }
                    break;
                // agrabah
                case 8:
                    if (settings["ag_2"] && !vars.completed_splits.TryGetValue("ag_2", out output_catch)) {
                        if (
                            vars.ag_puppies < 4 &&
                            (
                                (current.room == 6 && vars.check_world_puppies(current_world, new int[] {8}, 1)) ||
                                (current.room == 8 && vars.check_world_puppies(current_world, new int[] {1}, 2)) ||
                                (current.room == 11 && vars.check_world_puppies(current_world, new int[] {4}, 3)) ||
                                (current.room == 15 && vars.check_world_puppies(current_world, new int[] {4}, 4))
                            )
                        ) {
                            vars.ag_puppies += 1;
                        }
                        // pot scorpion
                        if (vars.ag_puppies == 4 && current.enemies_defeated[34] >= 1) {
                            var ag_trinities = vars.watchers["ag_trinities"];
                            ag_trinities.Update(game);
                            if (current.in_gummi > 0 && ag_trinities.Current == 252) {
                                vars.ag_puppies = 5;
                                return vars.completed_splits.Add("ag_2");
                            }
                        }
                    }
                    break;
                // atlantica
                case 9:
                    if (current.torn_page_count > old.torn_page_count) {
                        vars.atl_torn_page = true;
                    }
                    if (vars.atl_torn_page && current.in_gummi > 0) {
                        return vars.completed_splits.Add("atlantica_1") && settings["atlantica_1"];
                    }
                    break;
                // halloween town
                case 10:
                    if (settings["ht_2"] && !vars.completed_splits.TryGetValue("ht_2", out output_catch)) {
                        if (
                            vars.ht_puppies < 4 &&
                            (
                                (current.room == 3 && vars.check_world_puppies(current_world, new int[] {8}, 1)) ||
                                (current.room == 12 && vars.check_world_puppies(current_world, new int[] {1}, 2)) ||
                                (current.room == 8 && vars.check_world_puppies(current_world, new int[] {1}, 3)) ||
                                (current.room == 0 && vars.check_world_puppies(current_world, new int[] {8}, 4))
                            )
                        ) {
                            vars.ht_puppies += 1;
                        }
                        // chimera
                        if (vars.ht_puppies == 4 && current.enemies_defeated[48] >= 1) {
                            var ht_trinities = vars.watchers["ht_trinities"];
                            ht_trinities.Update(game);
                            if (current.in_gummi > 0 && ht_trinities.Current == 192) {
                                vars.ht_puppies = 5;
                                return vars.completed_splits.Add("ht_2");
                            }
                        }
                    }
                    break;
                // olympus coliseum
                case 11:
                    // gravity level
                    if (current.magic_level_flags[4] > old.magic_level_flags[4]) {
                        return settings["phil_cup"] && vars.completed_splits.Add("phil_cup");
                    }
                    if (current.room == 2 && current.scene == 7) {
                        int party_address = vars.party_address;
                        if (memory.ReadValue<ushort>(modules.First().BaseAddress + party_address) == 65535) {
                            // split when next available ability slot becomes combo plus in OC room 2 scene 7
                            int byte_count = 48 - vars.next_ability_slot_idx;
                            int ability_slot_address = 0x0;
                            int abilities_address = vars.abilities_address;
                            ability_slot_address = abilities_address + vars.next_ability_slot_idx;
                            var next_ability_slot = memory.ReadValue<byte>(modules.First().BaseAddress + ability_slot_address);
                            if (next_ability_slot == 134) {
                                return vars.completed_splits.Add("phil_cup_solo") && settings["phil_cup_solo"];
                            }
                            byte[] ability_slots = memory.ReadBytes(modules.First().BaseAddress + abilities_address, byte_count);
                            var ability_slots_slice = new byte[byte_count]; 
                            Array.Copy(ability_slots, vars.next_ability_slot_idx, ability_slots_slice, 0, byte_count);
                            for (int i = 0; i < ability_slots_slice.Length; i++) {
                                if (ability_slots[i] == 0) {
                                    vars.next_ability_slot_idx = i;
                                    break;
                                }
                            }
                        }
                    }
                    // can be adapted for plat
                    if (current.dest_behemoth_kills > old.dest_behemoth_kills) {
                        return vars.completed_splits.Add("hades_seed_49") && settings["hades_seed_49"];
                    }
                    // lion heart key blade
                    if (current.equips[36] == 1) {
                        return vars.completed_splits.Add("hades_seed_29") && settings["hades_seed_29"];
                    }
                    break;
                // monstro
                case 12:
                    if (settings["mo_2"] && !vars.completed_splits.TryGetValue("mo_2", out output_catch)) {
                        if (
                            vars.mo_puppies < 4 &&
                            (
                                (current.room == 10 && vars.check_world_puppies(current_world, new int[] {2}, 1)) ||
                                (current.room == 1 && vars.check_world_puppies(current_world, new int[] {2}, 2)) ||
                                (current.room == 7 && vars.check_world_puppies(current_world, new int[] {1}, 3)) ||
                                (current.room == 9 && vars.check_world_puppies(current_world, new int[] {4}, 4))
                            )
                        ) {
                            vars.mo_puppies += 1;
                        }
                        if (current.torn_page_count > old.torn_page_count) {
                            vars.mo_torn_page = true;
                        }
                        // grand ghost
                        if (vars.mo_puppies == 4 && current.enemies_defeated[92] >= 1) {
                            var mo_trinities = vars.watchers["mo_trinities"];
                            mo_trinities.Update(game);
                            if (current.in_gummi > 0 && mo_trinities.Current == 248) {
                                vars.mo_puppies = 5;
                                return vars.completed_splits.Add("mo_2");
                            }
                        }
                    }
                    break;
                // neverland
                case 13:
                    if (settings["nl_2"] && !vars.completed_splits.TryGetValue("nl_2", out output_catch)) {
                        if (
                            vars.nl_puppies < 4 &&
                            (
                                (current.room == 8 && vars.check_world_puppies(current_world, new int[] {2}, 1)) ||
                                (current.room == 0 && vars.check_world_puppies(current_world, new int[] {8}, 2)) ||
                                (current.room == 6 && vars.check_world_puppies(current_world, new int[] {4}, 3)) ||
                                (current.room == 2 && vars.check_world_puppies(current_world, new int[] {2}, 3))
                            )
                        ) {
                            vars.nl_puppies += 1;
                        }
                        // jet balloon
                        if (vars.nl_puppies == 4 && current.enemies_defeated[88] >= 1) {
                            var nl_trinities = vars.watchers["nl_trinities"];
                            nl_trinities.Update(game);
                            if (current.in_gummi > 0 && nl_trinities.Current == 131) {
                                vars.nl_puppies = 5;
                                return vars.completed_splits.Add("nl_2");
                            }
                        }
                    }
                    // backup on exp for phantom
                    if (current.room == 9 && current.scene == 1 && fight_exp) {
                        return vars.completed_splits.Add("nap_time") && settings["nap_time"];
                    }
                    break;
                // hollow bastion
                case 15:
                    // report count total - see rando some logic for how reports map
                    if (current.reports == 49406 && current.in_gummi > 0) {
                        return vars.completed_splits.Add("hb_2") && settings["hb_2"];
                    }
                    // exp necklace
                    if (current.room == 12 && current.scene == 2 && current.equips[2] > old.equips[2]) {
                        return settings["xemnas"];
                    }
                    break;
                // end of world
                case 16:
                    if (current.in_gummi > 0) {
                        return vars.completed_splits.Add("eow") && settings["eow"];
                    }
                    if (current.room == 29 && (settings["jj_complete_early"] || settings["jj_complete"])) {
                        vars.watchers["menu_open"].Update(game);
                        vars.watchers["chronicles_count"].Update(game);
                        vars.watchers["characters_one_count"].Update(game);
                        vars.watchers["characters_two_count"].Update(game);
                        var menu_open = vars.watchers["menu_open"];
                        var chronicles_count = vars.watchers["chronicles_count"];
                        var characters_one_count = vars.watchers["characters_one_count"];
                        var characters_two_count = vars.watchers["characters_two_count"];
                        vars.characters_complete = (
                            characters_one_count.Current == 39 &&
                            characters_two_count.Current == 64 &&
                            current.enemies_defeated[4] >= 1 && // bouncy wild
                            current.enemies_defeated[10] >= 1 && // sea neon
                            current.enemies_defeated[12] >= 1 && // sheltering zone
                            current.enemies_defeated[34] >= 1 && // pot scropion
                            current.enemies_defeated[44] >= 1 && // aquatank
                            current.enemies_defeated[46] >= 1 && // screw diver
                            current.enemies_defeated[48] >= 1 && // chimera
                            current.enemies_defeated[76] >= 1 && // pink agaricus
                            current.enemies_defeated[78] >= 1 && // neo shadow
                            current.enemies_defeated[80] >= 1 && // stealth soldier
                            current.enemies_defeated[82] >= 1 && // gigas shadow
                            current.enemies_defeated[84] >= 1 && // sniper wild
                            current.enemies_defeated[86] >= 1 && // black ballad
                            current.enemies_defeated[88] >= 1 && // jet balloon
                            current.enemies_defeated[92] >= 1 // grand ghost
                        );
                        vars.world_puppies_complete = current.puppy_count == 99;
                        vars.world_trinities_complete = (
                            current.trinity_counts[0] == 17 && // blue
                            current.trinity_counts[2] == 6 && // red
                            current.trinity_counts[3] == 9 && // green
                            current.trinity_counts[4] == 4 && // yellow
                            current.trinity_counts[5] == 10 // white
                        );
                        vars.world_mini_game_complete = current.mini_game_count == 8;
                        vars.journal_complete = (
                            chronicles_count.Current == 10 &&
                            current.reports == 63743 &&
                            vars.characters_complete &&
                            vars.world_puppies_complete &&
                            vars.world_trinities_complete
                        );
                        if (vars.journal_complete && menu_open.Old && !menu_open.Current) {
                            return vars.completed_splits.Add("jj_complete_early") && settings["jj_complete_early"];
                        }
                    }
                    if (old.room == 29 && current.room == 30 && vars.journal_complete) {
                        return vars.completed_splits.Add("jj_complete") && settings["jj_complete"];
                    }
                    break;
            }
        }
    }

    if (settings["plat_splits"]) {
        switch (current_world) {
            // traverse town splits
            case 3:
                // aero level
                if (!vars.aero_level_up && current.magic_level_flags[6] > old.magic_level_flags[6]) {
                    vars.aero_level_up = true;
                }
                // ultima
                if (current.equips[41] >= 1 && vars.aero_level_up) {
                    return vars.completed_splits.Add("tt_final") && settings["tt_final"];
                }
                break;
        }
        // synth splits
        vars.mats = (
            current.collected_items_1[0] >= 1 && // fury stone
            current.collected_items_1[1] >= 1 && // power stone
            current.collected_items_1[2] >= 1 && // energy stone
            current.collected_items_1[3] >= 1 && // blazing stone
            current.collected_items_1[4] >= 1 && // frost stone
            current.collected_items_1[5] >= 1 && // lightning stone
            current.collected_items_1[6] >= 1 && // dazzling stone
            current.collected_items_1[7] >= 1 && // stormy stone
            current.collected_items_2[3] >= 1 && // serenity power
            current.collected_items_2[5] >= 1 // mythril stone
        );
        if (vars.mats) {
            return vars.completed_splits.Add("each_mat") && settings["each_mat"];
        }
        // gummi splits
        if (current.in_gummi > 0) {
            int gummi_kills_address = vars.gummi_kills_address;
            vars.gummi_kills = memory.ReadValue<uint>(modules.First().BaseAddress + gummi_kills_address);            
        }
        if (vars.gummi_kills >= 2500) {
            return vars.completed_splits.Add("gummi_kills") && settings["gummi_kills"];
        }
    }

    if (settings["misc"]) {
        if (settings["coco"] && !vars.finished_nut) {
            if (settings["per_10"]) {
                // coconuts
                if (current.collected_items_2[46] > old.collected_items_2[46] && current.collected_items_2[46] % 10 == 0) {
                    return true;
                }
            }
            else if (settings["per_1"]) {
                // coconuts
                if (current.collected_items_2[46] > old.collected_items_2[46]) {
                    return true;
                }
            }
            // coconuts
            if (current.collected_items_2[46] == 99) {
                vars.finished_nut = true;
                return true;
            }
        }
    }

    // logic for handling death if you want to repeat splits or not and have one off
    if (death) {
        string back_split = vars.back_split;
        switch (back_split) {
            case "clay1":
                if (settings["manual_back_step"] || (!settings["manual_back_step"] && !settings["clayton_1"])) {
                    vars.clayton_1 = false;
                }
                break;
            case "pre_hook":
                if (settings["manual_back_step"] || (!settings["manual_back_step"] && !settings["pre_hook"])) {
                    vars.pre_hook = false;
                }
                break;
            case "fake":
                if (settings["manual_back_step"] || (!settings["manual_back_step"] && !settings["fake_guard"])) {
                    vars.fake_guard = false;
                }
                break;
            case "cloud2":
                if (settings["manual_back_step"] || (!settings["manual_back_step"] && !settings["cloud_2"])) {
                    vars.cloud_2 = false;
                }
                break;
            case "be3":
                if (settings["manual_back_step"] || (!settings["manual_back_step"] && !settings["behemoth_3"])) {
                    vars.behemoth_3 = false;
                }
                break;
            case "ds3":
                if (settings["manual_back_step"] || (!settings["manual_back_step"] && !settings["ds3"])) {
                    vars.ds3 = false;
                }
                break;
        }
    }
}

exit
{
    vars.booting = true;
    timer.IsGameTimePaused = true;  
}

init
{
    // game base address
    var gb = modules.First().BaseAddress;
    vars.offset = 0x0;
    vars.watchers = new Dictionary<string, MemoryWatcher>{};
    int epic_gl = memory.ReadValue<byte>(gb + 0x46A822);
    int epic_jp = memory.ReadValue<byte>(gb + 0x46A802);
    int steam_gl = memory.ReadValue<byte>(gb + 0x4698D2);
    int steam_jp = memory.ReadValue<byte>(gb + 0x469872);
    if (epic_gl == 106 || epic_jp == 106) {
        version = "EG Global";
        if (epic_jp == 106) {
            version = "EG Global";
        } else {
            version = "EG JP";
        }
        vars.watchers = new Dictionary<string, MemoryWatcher>{
            { "characters_one_count", new MemoryWatcher<byte>(gb + 0x2E9CB28) },
            { "characters_two_count", new MemoryWatcher<byte>(gb + 0x2E9CB2C) },
            { "chronicles_count", new MemoryWatcher<byte>(gb + 0x2E9DB10) },
            { "docked_world", new MemoryWatcher<ushort>(gb + 0x526A40) },
            { "gummi_destination_world", new MemoryWatcher<ushort>(gb + 0x508280) },
            { "gummi_start_world", new MemoryWatcher<ushort>(gb + 0x507C90) },
            { "hook_ship_flag", new MemoryWatcher<byte>(gb + 0xED751E) },
            { "newgame", new MemoryWatcher<byte>(gb + 0x2E9CBA4) },
            { "menu_open", new MemoryWatcher<bool>(gb + 0x232E980) },
        };
    } else {
        vars.offset = 0xA00;
        if (steam_gl == 106) {
            version = "Steam Global";
        } else if (steam_jp == 106) {
            version = "Steam JP";
        }
        vars.watchers = new Dictionary<string, MemoryWatcher>{
            { "characters_one_count", new MemoryWatcher<byte>(gb + 0x2E9C148) },
            { "characters_two_count", new MemoryWatcher<byte>(gb + 0x2E9C14C) },
            { "chronicles_count", new MemoryWatcher<byte>(gb + 0x2E9D130) },
            { "docked_world", new MemoryWatcher<ushort>(gb + 0x525D60) }, 
            { "gummi_destination_world", new MemoryWatcher<ushort>(gb + 0x507580) },
            { "gummi_start_world", new MemoryWatcher<ushort>(gb + 0x506F90) },
            { "hook_ship_flag", new MemoryWatcher<byte>(gb + 0xED6A1E) },
            { "newgame", new MemoryWatcher<byte>(gb + 0x2E9C1C8) },
            { "menu_open", new MemoryWatcher<bool>(gb + 0x232DFA0) },
       };
    }
    vars.watchers["difficulty"] = new MemoryWatcher<ushort>(gb + 0x2E0018C - vars.offset);
    vars.watchers["eow_scene"] = new MemoryWatcher<ushort>(gb + 0x2DEA96C - vars.offset);
    vars.watchers["neverland_scene"] = new MemoryWatcher<byte>(gb + 0x2DEB26D - vars.offset);
    vars.watchers["wl_trinities"] = new MemoryWatcher<ushort>(gb + 0x2DEB9CE - vars.offset);
    vars.watchers["dj_trinities"] = new MemoryWatcher<ushort>(gb + 0x2DEB9D2 - vars.offset);
    vars.watchers["ag_trinities"] = new MemoryWatcher<ushort>(gb + 0x2DEB9D4 - vars.offset);
    vars.watchers["mo_trinities"] = new MemoryWatcher<ushort>(gb + 0x2DEB9D6 - vars.offset);
    vars.watchers["ht_trinities"] = new MemoryWatcher<ushort>(gb + 0x2DEB9D8 - vars.offset);
    vars.watchers["nl_trinities"] = new MemoryWatcher<byte>(gb + 0x2DEB9DA - vars.offset);
    vars.watchers["slider_journal_entry"] = new MemoryWatcher<byte>(gb + 0x2DEB737 - vars.offset);
    vars.watchers["wl_puppies_1"] = new MemoryWatcher<byte>(gb + 0x2DEA390 - vars.offset);
    vars.watchers["wl_puppies_2"] = new MemoryWatcher<byte>(gb + 0x2DEA394 - vars.offset);
    vars.watchers["wl_puppies_3"] = new MemoryWatcher<byte>(gb + 0x2DEA398 - vars.offset);
    vars.watchers["dj_puppies_1"] = new MemoryWatcher<byte>(gb + 0x2DEA3A8 - vars.offset);
    vars.watchers["dj_puppies_2"] = new MemoryWatcher<byte>(gb + 0x2DEA3AC - vars.offset);
    vars.watchers["dj_puppies_3"] = new MemoryWatcher<byte>(gb + 0x2DEA3B0 - vars.offset);
    vars.watchers["dj_puppies_4"] = new MemoryWatcher<byte>(gb + 0x2DEA3B4 - vars.offset);
    vars.watchers["ag_puppies_1"] = new MemoryWatcher<byte>(gb + 0x2DEA3F8 - vars.offset);
    vars.watchers["ag_puppies_2"] = new MemoryWatcher<byte>(gb + 0x2DEA400 - vars.offset);
    vars.watchers["ag_puppies_3"] = new MemoryWatcher<byte>(gb + 0x2DEA404 - vars.offset);
    vars.watchers["ag_puppies_4"] = new MemoryWatcher<byte>(gb + 0x2DEA410 - vars.offset);
    vars.watchers["ht_puppies_1"] = new MemoryWatcher<byte>(gb + 0x2DEA458 - vars.offset);
    vars.watchers["ht_puppies_2"] = new MemoryWatcher<byte>(gb + 0x2DEA460 - vars.offset);
    vars.watchers["ht_puppies_3"] = new MemoryWatcher<byte>(gb + 0x2DEA464 - vars.offset);
    vars.watchers["ht_puppies_4"] = new MemoryWatcher<byte>(gb + 0x2DEA474 - vars.offset);
    vars.watchers["mo_puppies_1"] = new MemoryWatcher<byte>(gb + 0x2DEA420 - vars.offset);
    vars.watchers["mo_puppies_2"] = new MemoryWatcher<byte>(gb + 0x2DEA488 - vars.offset);
    vars.watchers["mo_puppies_3"] = new MemoryWatcher<byte>(gb + 0x2DEA498 - vars.offset);
    vars.watchers["mo_puppies_4"] = new MemoryWatcher<byte>(gb + 0x2DEA4A0 - vars.offset);
    vars.watchers["nl_puppies_1"] = new MemoryWatcher<byte>(gb + 0x2DEA4A4 - vars.offset);
    vars.watchers["nl_puppies_2"] = new MemoryWatcher<byte>(gb + 0x2DEA4A8 - vars.offset);
    vars.watchers["nl_puppies_3"] = new MemoryWatcher<byte>(gb + 0x2DEA4C0 - vars.offset);
    vars.party_address = 0x2DEA1EF - vars.offset;
    vars.abilities_address = 0x2DE9DA4 - vars.offset;
    vars.gummi_kills_address = 0x2DF5C98 - vars.offset;

    // resets all used variables on restart
    vars.completed_splits = new HashSet<string>();

    // traverse town vars
    vars.fake_guard = false;
    vars.oppo = false;
    vars.aero_level_up = false;

    // wonderland vars
    vars.wl_puppies = 0;

    // deep jungle vars
    vars.pw_gummis = 0;
    vars.clayton_1 = false;
    vars.clayton_2 = false;
    vars.dj_puppies = 0;

    // agrabah vars
    vars.ag_puppies = 0;

    // atlantica vars
    vars.atl_torn_page = false;

    // halloween town vars
    vars.ht_puppies = 0;

    // olympus coliseum vars
    vars.cloud_2 = false;
    vars.herc_cup = false;
    vars.next_ability_slot_idx = 0;

    // monstro vars
    vars.mo_torn_page = false;
    vars.mo_puppies = 0;

    // neverland vars
    vars.nl_puppies = 0;
    vars.pre_hook = false;

    // end of world vars
    vars.journal_complete = false;
    vars.behemoth_3 = false;
    vars.ds3 = false;

    // outside world vars
    vars.world_puppies_complete = false;
    vars.world_enemies_complete = false;
    vars.world_trinities_complete = false;
    vars.world_mini_game_complete = false;
    vars.gummi_kills = 0;

    // misc category vars
    vars.finished_nut = false;

    // manual back step vars
    vars.back_split = "";

    vars.check_world_puppies = (Func <int, int[], int, bool>)(
        (int world, int[] chest_values, int target) => {
            var puppy_check = new MemoryWatcher<byte>(modules.First().BaseAddress);
            if (target == 1) {
                puppy_check = vars.watchers["wl_puppies_1"];
            } else if (target == 2) {
                puppy_check = vars.watchers["wl_puppies_2"];
            } else {
                puppy_check = vars.watchers["wl_puppies_3"];
            }
            switch (world) {
                case 5:
                    if (target == 1) {
                        puppy_check = vars.watchers["dj_puppies_1"];
                    } else if (target == 2) {
                        puppy_check = vars.watchers["dj_puppies_2"];
                    } else if (target == 3) {
                        puppy_check = vars.watchers["dj_puppies_3"];
                    } else {
                        puppy_check = vars.watchers["dj_puppies_4"];
                    }
                    break;
                case 8:
                    if (target == 1) {
                        puppy_check = vars.watchers["ag_puppies_1"];
                    } else if (target == 2) {
                        puppy_check = vars.watchers["ag_puppies_2"];
                    } else if (target == 3) {
                        puppy_check = vars.watchers["ag_puppies_3"];
                    } else {
                        puppy_check = vars.watchers["ag_puppies_4"];
                    }
                    break;
                case 10:
                    if (target == 1) {
                        puppy_check = vars.watchers["ht_puppies_1"];
                    } else if (target == 2) {
                        puppy_check = vars.watchers["ht_puppies_2"];
                    } else if (target == 3) {
                        puppy_check = vars.watchers["ht_puppies_3"];
                    } else {
                        puppy_check = vars.watchers["ht_puppies_4"];
                    }
                    break;
                case 12:
                    if (target == 1) {
                        puppy_check = vars.watchers["mo_puppies_1"];
                    } else if (target == 2) {
                        puppy_check = vars.watchers["mo_puppies_2"];
                    } else if (target == 3) {
                        puppy_check = vars.watchers["mo_puppies_3"];
                    } else {
                        puppy_check = vars.watchers["mo_puppies_4"];
                    }
                    break;
                case 13:
                    if (target == 1) {
                        puppy_check = vars.watchers["nl_puppies_1"];
                    } else if (target == 2) {
                        puppy_check = vars.watchers["nl_puppies_2"];
                    } else {
                        puppy_check = vars.watchers["nl_puppies_3"];
                    }
                    break;
            }
            puppy_check.Update(game);
            foreach (int chest_val in chest_values) {
                if (puppy_check.Current - puppy_check.Old == chest_val) {
                    return true;
                }
            }
            return false;
        }
    );

    timer.IsGameTimePaused = false;
}

reset
{
    // -1 value of 4 byte for world
    if (current.scene == 0 && current.room == 0 && current.world == 65535 && old.world != 65535) {
        if (settings["boss_rush"]) {
            File.Copy(@"Boss Rush\001_Darkside 1.dat", vars.autosavedst, true);
        }
        return true;
    }
}

update
{
    var output_catch = "";
    if (
        (settings["ship"] && !vars.completed_splits.TryGetValue("ship", out output_catch)) || (settings["ship_early"] && !vars.completed_splits.TryGetValue("ship_early", out output_catch)) ||
        (settings["wl_2"] && !vars.completed_splits.TryGetValue("wl_2", out output_catch)) || (settings["dj_2"] && !vars.completed_splits.TryGetValue("dj_2", out output_catch)) ||
        (settings["ag_2"] && !vars.completed_splits.TryGetValue("ag_2", out output_catch)) || (settings["ht_2"] && !vars.completed_splits.TryGetValue("ht_2", out output_catch)) ||
        (settings["mo_2"] && !vars.completed_splits.TryGetValue("mo_2", out output_catch)) || (settings["nl_2"] && !vars.completed_splits.TryGetValue("nl_2", out output_catch))
    ) {
        vars.watchers["gummi_start_world"].Update(game);
        vars.watchers["gummi_destination_world"].Update(game);
    }
    if (settings["atl_dock"] && !vars.completed_splits.TryGetValue("atl_dock", out output_catch)) {
        vars.watchers["docked_world"].Update(game);
    }

    if (vars.booting && current.world == 65535) {
        vars.booting = false;
    }
}

isLoading
{
    vars.summon_timer = current.summon_load ? vars.summon_timer + (current.paused ? 0 : 1) : 0;

    return (
        (
            current.load
            || !current.black
            || (current.white == 128 && !current.cutscene)
            || vars.summon_timer > 30
        )
        && !current.paused
    )
    || current.save_load
    || current.party_load
    || (current.load_2 && current.sora_hp == 0)
    || vars.booting;
}