diff --git a/worlds/jakanddaxter/GameID.py b/worlds/jakanddaxter/GameID.py index 63e1bb1002..12d0079483 100644 --- a/worlds/jakanddaxter/GameID.py +++ b/worlds/jakanddaxter/GameID.py @@ -1,2 +1,5 @@ -# All Jak And Daxter IDs will be offset by this number. +# All Jak And Daxter IDs must be offset by this number. game_id = 74680000 + +# The name of the game. +game_name = "Jak and Daxter: The Precursor Legacy" diff --git a/worlds/jakanddaxter/Items.py b/worlds/jakanddaxter/Items.py index 2690d68f85..ee94ca55e0 100644 --- a/worlds/jakanddaxter/Items.py +++ b/worlds/jakanddaxter/Items.py @@ -1,8 +1,9 @@ from BaseClasses import Item +from .GameID import game_id, game_name class JakAndDaxterItem(Item): - game: str = "Jak and Daxter: The Precursor Legacy" + game: str = game_name # Items Found Multiple Times @@ -20,7 +21,11 @@ special_item_table = { 2216: "Blue Eco Switch", 2217: "Gladiator's Pontoons", 2218: "Yellow Eco Switch", - 2219: "Lurker Fort Gate" + 2219: "Lurker Fort Gate", + 2220: "Free The Yellow Sage", + 2221: "Free The Red Sage", + 2222: "Free The Blue Sage", + 2223: "Free The Green Sage" } # All Items diff --git a/worlds/jakanddaxter/Locations.py b/worlds/jakanddaxter/Locations.py index 156e422eea..9d03297e4a 100644 --- a/worlds/jakanddaxter/Locations.py +++ b/worlds/jakanddaxter/Locations.py @@ -1,9 +1,10 @@ from BaseClasses import Location +from .GameID import game_id, game_name from .locs import CellLocations, SpecialLocations, ScoutLocations class JakAndDaxterLocation(Location): - game: str = "Jak and Daxter: The Precursor Legacy" + game: str = game_name # All Locations diff --git a/worlds/jakanddaxter/Regions.py b/worlds/jakanddaxter/Regions.py index 627efc85c6..59cd9e5ff7 100644 --- a/worlds/jakanddaxter/Regions.py +++ b/worlds/jakanddaxter/Regions.py @@ -1,6 +1,7 @@ import typing from enum import Enum from BaseClasses import MultiWorld, Region +from .GameID import game_id, game_name from .Options import JakAndDaxterOptions from .Locations import JakAndDaxterLocation, location_table from .locs import CellLocations, SpecialLocations, ScoutLocations @@ -34,6 +35,7 @@ class JakAndDaxterSubLevel(int, Enum): SNOWY_MOUNTAIN_FLUT_FLUT = 5 SNOWY_MOUNTAIN_LURKER_FORT = 6 GOL_AND_MAIAS_CITADEL_ROTATING_TOWER = 7 + GOL_AND_MAIAS_CITADEL_FINAL_BOSS = 8 level_table: typing.Dict[JakAndDaxterLevel, str] = { @@ -63,12 +65,13 @@ subLevel_table: typing.Dict[JakAndDaxterSubLevel, str] = { JakAndDaxterSubLevel.MOUNTAIN_PASS_SHORTCUT: "Mountain Pass Shortcut", JakAndDaxterSubLevel.SNOWY_MOUNTAIN_FLUT_FLUT: "Snowy Mountain Flut Flut", JakAndDaxterSubLevel.SNOWY_MOUNTAIN_LURKER_FORT: "Snowy Mountain Lurker Fort", - JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_ROTATING_TOWER: "Gol and Maia's Citadel Rotating Tower" + JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_ROTATING_TOWER: "Gol and Maia's Citadel Rotating Tower", + JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_FINAL_BOSS: "Gol and Maia's Citadel Final Boss" } class JakAndDaxterRegion(Region): - game: str = "Jak and Daxter: The Precursor Legacy" + game: str = game_name def create_regions(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int): @@ -198,16 +201,20 @@ def create_regions(multiworld: MultiWorld, options: JakAndDaxterOptions, player: region_gmc = create_region(player, multiworld, level_table[JakAndDaxterLevel.GOL_AND_MAIAS_CITADEL]) create_locations(region_gmc, { **{k: CellLocations.locGMC_cellTable[k] for k in {96, 97, 98}}, - **{k: ScoutLocations.locGMC_scoutTable[k] for k in {206, 207, 208, 209, 210, 211}} + **{k: ScoutLocations.locGMC_scoutTable[k] for k in {206, 207, 208, 209, 210, 211}}, + **{k: SpecialLocations.loc_specialTable[k] for k in {2220, 2221, 2222}} }) sub_region_gmcrt = create_subregion(region_gmc, subLevel_table[JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_ROTATING_TOWER]) create_locations(sub_region_gmcrt, { **{k: CellLocations.locGMC_cellTable[k] for k in {99, 100}}, - **{k: ScoutLocations.locGMC_scoutTable[k] for k in {212}} + **{k: ScoutLocations.locGMC_scoutTable[k] for k in {212}}, + **{k: SpecialLocations.loc_specialTable[k] for k in {2223}} }) + create_subregion(sub_region_gmcrt, subLevel_table[JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_FINAL_BOSS]) + def create_region(player: int, multiworld: MultiWorld, name: str) -> JakAndDaxterRegion: region = JakAndDaxterRegion(name, player, multiworld) @@ -223,5 +230,6 @@ def create_subregion(parent: Region, name: str) -> JakAndDaxterRegion: return region -def create_locations(region: Region, locs: typing.Dict[int, str]): - region.locations += [JakAndDaxterLocation(region.player, location_table[loc], loc, region) for loc in locs] +def create_locations(region: Region, locations: typing.Dict[int, str]): + region.locations += [JakAndDaxterLocation(region.player, location_table[loc], game_id + loc, region) + for loc in locations] diff --git a/worlds/jakanddaxter/Rules.py b/worlds/jakanddaxter/Rules.py index 3822b42f7b..4165ea8d4a 100644 --- a/worlds/jakanddaxter/Rules.py +++ b/worlds/jakanddaxter/Rules.py @@ -18,19 +18,19 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) JakAndDaxterLevel.SANDOVER_VILLAGE, JakAndDaxterLevel.FORBIDDEN_JUNGLE) - connect_subregions(multiworld, player, - JakAndDaxterLevel.FORBIDDEN_JUNGLE, - JakAndDaxterSubLevel.FORBIDDEN_JUNGLE_PLANT_ROOM, - lambda state: state.has(item_table[2216], player)) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.FORBIDDEN_JUNGLE, + JakAndDaxterSubLevel.FORBIDDEN_JUNGLE_PLANT_ROOM, + lambda state: state.has(item_table[2216], player)) connect_regions(multiworld, player, JakAndDaxterLevel.SANDOVER_VILLAGE, JakAndDaxterLevel.SENTINEL_BEACH) - connect_subregions(multiworld, player, - JakAndDaxterLevel.SENTINEL_BEACH, - JakAndDaxterSubLevel.SENTINEL_BEACH_CANNON_TOWER, - lambda state: state.has(item_table[2216], player)) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.SENTINEL_BEACH, + JakAndDaxterSubLevel.SENTINEL_BEACH_CANNON_TOWER, + lambda state: state.has(item_table[2216], player)) connect_regions(multiworld, player, JakAndDaxterLevel.SANDOVER_VILLAGE, @@ -59,20 +59,20 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) JakAndDaxterLevel.BOGGY_SWAMP, lambda state: state.has(item_table[2217], player)) - connect_subregions(multiworld, player, - JakAndDaxterLevel.BOGGY_SWAMP, - JakAndDaxterSubLevel.BOGGY_SWAMP_FLUT_FLUT, - lambda state: state.has(item_table[2215], player)) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.BOGGY_SWAMP, + JakAndDaxterSubLevel.BOGGY_SWAMP_FLUT_FLUT, + lambda state: state.has(item_table[2215], player)) connect_regions(multiworld, player, JakAndDaxterLevel.ROCK_VILLAGE, JakAndDaxterLevel.MOUNTAIN_PASS, lambda state: state.has(item_table[2217], player) and state.has(item_table[0], player, 45)) - connect_subregions(multiworld, player, - JakAndDaxterLevel.MOUNTAIN_PASS, - JakAndDaxterSubLevel.MOUNTAIN_PASS_SHORTCUT, - lambda state: state.has(item_table[2218], player)) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.MOUNTAIN_PASS, + JakAndDaxterSubLevel.MOUNTAIN_PASS_SHORTCUT, + lambda state: state.has(item_table[2218], player)) connect_regions(multiworld, player, JakAndDaxterLevel.MOUNTAIN_PASS, @@ -86,15 +86,15 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) JakAndDaxterLevel.VOLCANIC_CRATER, JakAndDaxterLevel.SNOWY_MOUNTAIN) - connect_subregions(multiworld, player, - JakAndDaxterLevel.SNOWY_MOUNTAIN, - JakAndDaxterSubLevel.SNOWY_MOUNTAIN_FLUT_FLUT, - lambda state: state.has(item_table[2215], player)) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.SNOWY_MOUNTAIN, + JakAndDaxterSubLevel.SNOWY_MOUNTAIN_FLUT_FLUT, + lambda state: state.has(item_table[2215], player)) - connect_subregions(multiworld, player, - JakAndDaxterLevel.SNOWY_MOUNTAIN, - JakAndDaxterSubLevel.SNOWY_MOUNTAIN_LURKER_FORT, - lambda state: state.has(item_table[2219], player)) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.SNOWY_MOUNTAIN, + JakAndDaxterSubLevel.SNOWY_MOUNTAIN_LURKER_FORT, + lambda state: state.has(item_table[2219], player)) connect_regions(multiworld, player, JakAndDaxterLevel.VOLCANIC_CRATER, @@ -105,13 +105,22 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) JakAndDaxterLevel.LAVA_TUBE, JakAndDaxterLevel.GOL_AND_MAIAS_CITADEL) + connect_region_to_sub(multiworld, player, + JakAndDaxterLevel.GOL_AND_MAIAS_CITADEL, + JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_ROTATING_TOWER, + lambda state: state.has(item_table[2220], player) + and state.has(item_table[2221], player) + and state.has(item_table[2222], player)) + connect_subregions(multiworld, player, - JakAndDaxterLevel.GOL_AND_MAIAS_CITADEL, JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_ROTATING_TOWER, - # lambda state: state.has(item_table[96], player) - # and state.has(item_table[97], player) - # and state.has(item_table[98], player)) - lambda state: state.has(item_table[0], player, 75)) + JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_FINAL_BOSS, + lambda state: state.has(item_table[2223], player)) + + multiworld.completion_condition[player] = lambda state: state.can_reach( + multiworld.get_region(subLevel_table[JakAndDaxterSubLevel.GOL_AND_MAIAS_CITADEL_FINAL_BOSS], player), + "Region", + player) def connect_regions(multiworld: MultiWorld, player: int, source: JakAndDaxterLevel, target: JakAndDaxterLevel, @@ -121,8 +130,15 @@ def connect_regions(multiworld: MultiWorld, player: int, source: JakAndDaxterLev source_region.connect(target_region, rule=rule) -def connect_subregions(multiworld: MultiWorld, player: int, source: JakAndDaxterLevel, target: JakAndDaxterSubLevel, - rule=None): +def connect_region_to_sub(multiworld: MultiWorld, player: int, source: JakAndDaxterLevel, target: JakAndDaxterSubLevel, + rule=None): source_region = multiworld.get_region(level_table[source], player) target_region = multiworld.get_region(subLevel_table[target], player) source_region.connect(target_region, rule=rule) + + +def connect_subregions(multiworld: MultiWorld, player: int, source: JakAndDaxterSubLevel, target: JakAndDaxterSubLevel, + rule=None): + source_region = multiworld.get_region(subLevel_table[source], player) + target_region = multiworld.get_region(subLevel_table[target], player) + source_region.connect(target_region, rule=rule) diff --git a/worlds/jakanddaxter/__init__.py b/worlds/jakanddaxter/__init__.py index 6e140cde56..d2a8db9982 100644 --- a/worlds/jakanddaxter/__init__.py +++ b/worlds/jakanddaxter/__init__.py @@ -5,12 +5,12 @@ from .Regions import JakAndDaxterLevel, JakAndDaxterSubLevel, JakAndDaxterRegion create_regions from .Rules import set_rules from .Items import JakAndDaxterItem, item_table, generic_item_table, special_item_table -from .GameID import game_id +from .GameID import game_id, game_name from ..AutoWorld import World class JakAndDaxterWorld(World): - game: str = "Jak and Daxter: The Precursor Legacy" + game: str = game_name data_version = 1 required_client_version = (0, 4, 5) diff --git a/worlds/jakanddaxter/locs/SpecialLocations.py b/worlds/jakanddaxter/locs/SpecialLocations.py index 6a21f6db1a..c93c86f02b 100644 --- a/worlds/jakanddaxter/locs/SpecialLocations.py +++ b/worlds/jakanddaxter/locs/SpecialLocations.py @@ -1,4 +1,4 @@ -# Special Locations start at ID 2213 and end at ID 2219. +# Special Locations start at ID 2213 and end at ID 22xx. loc_specialTable = { 2213: "Fisherman's Boat", @@ -7,5 +7,9 @@ loc_specialTable = { 2216: "Blue Eco Switch", 2217: "Gladiator's Pontoons", 2218: "Yellow Eco Switch", - 2219: "Lurker Fort Gate" + 2219: "Lurker Fort Gate", + 2220: "Free The Yellow Sage", + 2221: "Free The Red Sage", + 2222: "Free The Blue Sage", + 2223: "Free The Green Sage" }