mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-23 14:43:21 -07:00
Jak and Daxter - Gondola, Pontoons, Rules, Regions, and Client Update
* Jak 1: Overhaul of regions, rules, and special locations. Updated game info page. * Jak 1: Preparations for Alpha. Reintroducing automatic startup in client. Updating docs, readme, codeowners.
This commit is contained in:
committed by
GitHub
parent
064ae557d2
commit
e76df684b5
@@ -31,6 +31,7 @@ Currently, the following games are supported:
|
||||
* Super Mario World
|
||||
* Pokémon Red and Blue
|
||||
* Hylics 2
|
||||
* Jak and Daxter: The Precursor Legacy
|
||||
* Overcooked! 2
|
||||
* Zillion
|
||||
* Lufia II Ancient Cave
|
||||
|
||||
@@ -82,6 +82,9 @@
|
||||
# Hylics 2
|
||||
/worlds/hylics2/ @TRPG0
|
||||
|
||||
# Jak and Daxter: The Precursor Legacy
|
||||
/worlds/jakanddaxter/ @massimilianodelliubaldini
|
||||
|
||||
# Kirby's Dream Land 3
|
||||
/worlds/kdl3/ @Silvris
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import subprocess
|
||||
import typing
|
||||
import asyncio
|
||||
import colorama
|
||||
import pymem
|
||||
from pymem.exception import ProcessNotFound, ProcessError
|
||||
|
||||
import Utils
|
||||
from NetUtils import ClientStatus
|
||||
@@ -137,45 +139,52 @@ class JakAndDaxterContext(CommonContext):
|
||||
|
||||
|
||||
async def run_game(ctx: JakAndDaxterContext):
|
||||
exec_directory = ""
|
||||
try:
|
||||
exec_directory = Utils.get_settings()["jakanddaxter_options"]["root_directory"]
|
||||
files_in_path = os.listdir(exec_directory)
|
||||
if ".git" in files_in_path:
|
||||
# Indicates the user is running from source, append expected subdirectory appropriately.
|
||||
exec_directory = os.path.join(exec_directory, "out", "build", "Release", "bin")
|
||||
else:
|
||||
# Indicates the user is running from the official launcher, a mod launcher, or otherwise.
|
||||
# We'll need to handle version numbers in the path somehow...
|
||||
exec_directory = os.path.join(exec_directory, "versions", "official")
|
||||
latest_version = list(reversed(os.listdir(exec_directory)))[0]
|
||||
exec_directory = os.path.join(exec_directory, str(latest_version))
|
||||
except FileNotFoundError:
|
||||
logger.error(f"Unable to locate directory {exec_directory}, "
|
||||
f"unable to locate game executable.")
|
||||
return
|
||||
except KeyError as e:
|
||||
logger.error(f"Hosts.yaml does not contain {e.args[0]}, "
|
||||
f"unable to locate game executable.")
|
||||
return
|
||||
|
||||
gk = os.path.join(exec_directory, "gk.exe")
|
||||
goalc = os.path.join(exec_directory, "goalc.exe")
|
||||
# If you're running the game through the mod launcher, these may already be running.
|
||||
# If they are not running, try to start them.
|
||||
gk_running = False
|
||||
try:
|
||||
pymem.Pymem("gk.exe") # The GOAL Kernel
|
||||
gk_running = True
|
||||
except ProcessNotFound:
|
||||
logger.info("Game not running, attempting to start.")
|
||||
|
||||
goalc_running = False
|
||||
try:
|
||||
pymem.Pymem("goalc.exe") # The GOAL Compiler and REPL
|
||||
goalc_running = True
|
||||
except ProcessNotFound:
|
||||
logger.info("Compiler not running, attempting to start.")
|
||||
|
||||
# Don't mind all the arguments, they are exactly what you get when you run "task boot-game" or "task repl".
|
||||
await asyncio.create_subprocess_exec(
|
||||
gk,
|
||||
"-v", "--game jak1", "--", "-boot", "-fakeiso", "-debug",
|
||||
stderr=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stdin=subprocess.DEVNULL)
|
||||
# TODO - Support other OS's. cmd for some reason does not work with goalc.
|
||||
if not gk_running:
|
||||
try:
|
||||
gk_path = Utils.get_settings()["jakanddaxter_options"]["root_directory"]
|
||||
gk_path = os.path.normpath(gk_path)
|
||||
gk_path = os.path.join(gk_path, "gk.exe")
|
||||
except AttributeError as e:
|
||||
logger.error(f"Hosts.yaml does not contain {e.args[0]}, unable to locate game executables.")
|
||||
return
|
||||
|
||||
# You MUST launch goalc as a console application, so powershell/cmd/bash/etc is the program
|
||||
# and goalc is just an argument. It HAS to be this way.
|
||||
# TODO - Support other OS's.
|
||||
await asyncio.create_subprocess_exec(
|
||||
"powershell.exe",
|
||||
goalc, "--user-auto", "--game jak1")
|
||||
if gk_path:
|
||||
gk_process = subprocess.Popen(
|
||||
["powershell.exe", gk_path, "--game jak1", "--", "-v", "-boot", "-fakeiso", "-debug"],
|
||||
creationflags=subprocess.CREATE_NEW_CONSOLE) # These need to be new consoles for stability.
|
||||
|
||||
if not goalc_running:
|
||||
try:
|
||||
goalc_path = Utils.get_settings()["jakanddaxter_options"]["root_directory"]
|
||||
goalc_path = os.path.normpath(goalc_path)
|
||||
goalc_path = os.path.join(goalc_path, "goalc.exe")
|
||||
except AttributeError as e:
|
||||
logger.error(f"Hosts.yaml does not contain {e.args[0]}, unable to locate game executables.")
|
||||
return
|
||||
|
||||
if goalc_path:
|
||||
goalc_process = subprocess.Popen(
|
||||
["powershell.exe", goalc_path, "--game jak1"],
|
||||
creationflags=subprocess.CREATE_NEW_CONSOLE) # These need to be new consoles for stability.
|
||||
|
||||
# Auto connect the repl and memr agents. Sleep 5 because goalc takes just a little bit of time to load,
|
||||
# and it's not something we can await.
|
||||
@@ -189,7 +198,6 @@ async def main():
|
||||
Utils.init_logging("JakAndDaxterClient", exception_logger="Client")
|
||||
|
||||
ctx = JakAndDaxterContext(None, None)
|
||||
|
||||
ctx.server_task = asyncio.create_task(server_loop(ctx), name="server loop")
|
||||
ctx.repl_task = create_task_log_exception(ctx.run_repl_loop())
|
||||
ctx.memr_task = create_task_log_exception(ctx.run_memr_loop())
|
||||
@@ -199,7 +207,7 @@ async def main():
|
||||
ctx.run_cli()
|
||||
|
||||
# Find and run the game (gk) and compiler/repl (goalc).
|
||||
# await run_game(ctx)
|
||||
await run_game(ctx)
|
||||
await ctx.exit_event.wait()
|
||||
await ctx.shutdown()
|
||||
|
||||
|
||||
@@ -42,16 +42,18 @@ scout_item_table = {
|
||||
# These are special items representing unique unlocks in the world. Notice that their Item ID equals their
|
||||
# respective Location ID. Like scout flies, this is necessary for game<->archipelago communication.
|
||||
special_item_table = {
|
||||
5: "Fisherman's Boat",
|
||||
4: "Jungle Elevator",
|
||||
2: "Blue Eco Switch",
|
||||
17: "Flut Flut",
|
||||
60: "Yellow Eco Switch",
|
||||
63: "Snowy Fort Gate",
|
||||
71: "Freed The Blue Sage",
|
||||
72: "Freed The Red Sage",
|
||||
73: "Freed The Yellow Sage",
|
||||
70: "Freed The Green Sage",
|
||||
5: "Fisherman's Boat", # Unlocks 14 checks in Misty Island
|
||||
4: "Jungle Elevator", # Unlocks 2 checks in Forbidden Jungle
|
||||
2: "Blue Eco Switch", # Unlocks 1 check in Jungle and 1 in Beach
|
||||
17: "Flut Flut", # Unlocks 2 checks in Swamp and 2 in Snowy
|
||||
33: "Warrior's Pontoons", # Unlocks 14 checks in Swamp and everything post-Rock Village
|
||||
105: "Snowy Mountain Gondola", # Unlocks 15 checks in Snowy Mountain
|
||||
60: "Yellow Eco Switch", # Unlocks 1 check in Pass and 1 in Snowy
|
||||
63: "Snowy Fort Gate", # Unlocks 3 checks in Snowy Mountain
|
||||
71: "Freed The Blue Sage", # 1 of 3 unlocks for the final staircase and 2 checks in Citadel
|
||||
72: "Freed The Red Sage", # 1 of 3 unlocks for the final staircase and 2 checks in Citadel
|
||||
73: "Freed The Yellow Sage", # 1 of 3 unlocks for the final staircase and 2 checks in Citadel
|
||||
70: "Freed The Green Sage", # Unlocks the final elevator
|
||||
}
|
||||
|
||||
# All Items
|
||||
|
||||
@@ -47,11 +47,8 @@ class Jak1SubLevel(int, Enum):
|
||||
FORBIDDEN_JUNGLE_SWITCH_ROOM = auto()
|
||||
FORBIDDEN_JUNGLE_PLANT_ROOM = auto()
|
||||
SENTINEL_BEACH_CANNON_TOWER = auto()
|
||||
PRECURSOR_BASIN_BLUE_RINGS = auto()
|
||||
LOST_PRECURSOR_CITY_SUNKEN_ROOM = auto()
|
||||
LOST_PRECURSOR_CITY_HELIX_ROOM = auto()
|
||||
ROCK_VILLAGE_PONTOON_BRIDGE = auto()
|
||||
BOGGY_SWAMP_FLUT_FLUT = auto()
|
||||
MOUNTAIN_PASS_RACE = auto()
|
||||
MOUNTAIN_PASS_SHORTCUT = auto()
|
||||
SNOWY_MOUNTAIN_FLUT_FLUT = auto()
|
||||
SNOWY_MOUNTAIN_LURKER_FORT = auto()
|
||||
@@ -76,15 +73,15 @@ level_table: typing.Dict[Jak1Level, Jak1LevelInfo] = {
|
||||
Jak1Level.FIRE_CANYON:
|
||||
Jak1LevelInfo("Fire Canyon", 50),
|
||||
Jak1Level.ROCK_VILLAGE:
|
||||
Jak1LevelInfo("Rock Village", 50),
|
||||
Jak1LevelInfo("Rock Village", 43),
|
||||
Jak1Level.PRECURSOR_BASIN:
|
||||
Jak1LevelInfo("Precursor Basin", 200),
|
||||
Jak1Level.LOST_PRECURSOR_CITY:
|
||||
Jak1LevelInfo("Lost Precursor City", 133),
|
||||
Jak1LevelInfo("Lost Precursor City", 200),
|
||||
Jak1Level.BOGGY_SWAMP:
|
||||
Jak1LevelInfo("Boggy Swamp", 177),
|
||||
Jak1Level.MOUNTAIN_PASS:
|
||||
Jak1LevelInfo("Mountain Pass", 0),
|
||||
Jak1LevelInfo("Mountain Pass", 50),
|
||||
Jak1Level.VOLCANIC_CRATER:
|
||||
Jak1LevelInfo("Volcanic Crater", 50),
|
||||
Jak1Level.SPIDER_CAVE:
|
||||
@@ -104,16 +101,10 @@ sub_level_table: typing.Dict[Jak1SubLevel, Jak1LevelInfo] = {
|
||||
Jak1LevelInfo("Forbidden Jungle Plant Room", 27),
|
||||
Jak1SubLevel.SENTINEL_BEACH_CANNON_TOWER:
|
||||
Jak1LevelInfo("Sentinel Beach Cannon Tower", 22),
|
||||
Jak1SubLevel.PRECURSOR_BASIN_BLUE_RINGS:
|
||||
Jak1LevelInfo("Precursor Basin Blue Rings", 0), # Another virtual location, no orbs.
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_SUNKEN_ROOM:
|
||||
Jak1LevelInfo("Lost Precursor City Sunken Room", 37),
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_HELIX_ROOM:
|
||||
Jak1LevelInfo("Lost Precursor City Helix Room", 30),
|
||||
Jak1SubLevel.ROCK_VILLAGE_PONTOON_BRIDGE:
|
||||
Jak1LevelInfo("Rock Village Pontoon Bridge", 7),
|
||||
Jak1SubLevel.BOGGY_SWAMP_FLUT_FLUT:
|
||||
Jak1LevelInfo("Boggy Swamp Flut Flut", 23),
|
||||
Jak1SubLevel.MOUNTAIN_PASS_RACE:
|
||||
Jak1LevelInfo("Mountain Pass Race", 50),
|
||||
Jak1SubLevel.MOUNTAIN_PASS_SHORTCUT:
|
||||
Jak1LevelInfo("Mountain Pass Shortcut", 0),
|
||||
Jak1SubLevel.SNOWY_MOUNTAIN_FLUT_FLUT:
|
||||
@@ -177,26 +168,20 @@ def create_regions(multiworld: MultiWorld, options: JakAndDaxterOptions, player:
|
||||
|
||||
region_rv = create_region(player, multiworld, Jak1Level.ROCK_VILLAGE)
|
||||
create_cell_locations(region_rv, Cells.locRV_cellTable)
|
||||
create_fly_locations(region_rv, Scouts.locRV_scoutTable)
|
||||
create_fly_locations(region_rv, {k: Scouts.locRV_scoutTable[k]
|
||||
for k in {76, 131148, 196684, 262220, 65612, 327756}})
|
||||
create_special_locations(region_rv, {k: Specials.loc_specialTable[k] for k in {33}})
|
||||
|
||||
sub_region_rvpb = create_subregion(region_rv, Jak1SubLevel.ROCK_VILLAGE_PONTOON_BRIDGE)
|
||||
create_fly_locations(sub_region_rvpb, {k: Scouts.locRV_scoutTable[k] for k in {393292}})
|
||||
|
||||
region_pb = create_region(player, multiworld, Jak1Level.PRECURSOR_BASIN)
|
||||
create_cell_locations(region_pb, {k: Cells.locPB_cellTable[k] for k in {54, 53, 52, 56, 55, 58}})
|
||||
create_cell_locations(region_pb, Cells.locPB_cellTable)
|
||||
create_fly_locations(region_pb, Scouts.locPB_scoutTable)
|
||||
|
||||
sub_region_pbbr = create_subregion(region_pb, Jak1SubLevel.PRECURSOR_BASIN_BLUE_RINGS)
|
||||
create_cell_locations(sub_region_pbbr, {k: Cells.locPB_cellTable[k] for k in {59}})
|
||||
|
||||
region_lpc = create_region(player, multiworld, Jak1Level.LOST_PRECURSOR_CITY)
|
||||
create_cell_locations(region_lpc, {k: Cells.locLPC_cellTable[k] for k in {45, 48, 44, 51}})
|
||||
create_fly_locations(region_lpc, {k: Scouts.locLPC_scoutTable[k]
|
||||
for k in {262193, 131121, 393265, 196657, 49, 65585}})
|
||||
|
||||
sub_region_lpcsr = create_subregion(region_lpc, Jak1SubLevel.LOST_PRECURSOR_CITY_SUNKEN_ROOM)
|
||||
create_cell_locations(sub_region_lpcsr, {k: Cells.locLPC_cellTable[k] for k in {47}})
|
||||
create_fly_locations(region_lpc, {k: Scouts.locLPC_scoutTable[k] for k in {327729}})
|
||||
|
||||
sub_region_lpchr = create_subregion(region_lpc, Jak1SubLevel.LOST_PRECURSOR_CITY_HELIX_ROOM)
|
||||
create_cell_locations(sub_region_lpchr, {k: Cells.locLPC_cellTable[k] for k in {46, 50}})
|
||||
create_cell_locations(region_lpc, Cells.locLPC_cellTable)
|
||||
create_fly_locations(region_lpc, Scouts.locLPC_scoutTable)
|
||||
|
||||
region_bs = create_region(player, multiworld, Jak1Level.BOGGY_SWAMP)
|
||||
create_cell_locations(region_bs, {k: Cells.locBS_cellTable[k] for k in {36, 38, 39, 40, 41, 42}})
|
||||
@@ -207,18 +192,16 @@ def create_regions(multiworld: MultiWorld, options: JakAndDaxterOptions, player:
|
||||
create_fly_locations(sub_region_bsff, {k: Scouts.locBS_scoutTable[k] for k in {327723, 131115}})
|
||||
|
||||
region_mp = create_region(player, multiworld, Jak1Level.MOUNTAIN_PASS)
|
||||
create_cell_locations(region_mp, {k: Cells.locMP_cellTable[k] for k in {86}})
|
||||
create_cell_locations(region_mp, {k: Cells.locMP_cellTable[k] for k in {86, 87}})
|
||||
create_fly_locations(region_mp, Scouts.locMP_scoutTable)
|
||||
|
||||
sub_region_mpr = create_subregion(region_mp, Jak1SubLevel.MOUNTAIN_PASS_RACE)
|
||||
create_cell_locations(sub_region_mpr, {k: Cells.locMP_cellTable[k] for k in {87}})
|
||||
create_fly_locations(sub_region_mpr, Scouts.locMP_scoutTable)
|
||||
|
||||
sub_region_mps = create_subregion(sub_region_mpr, Jak1SubLevel.MOUNTAIN_PASS_SHORTCUT)
|
||||
sub_region_mps = create_subregion(region_mp, Jak1SubLevel.MOUNTAIN_PASS_SHORTCUT)
|
||||
create_cell_locations(sub_region_mps, {k: Cells.locMP_cellTable[k] for k in {110}})
|
||||
|
||||
region_vc = create_region(player, multiworld, Jak1Level.VOLCANIC_CRATER)
|
||||
create_cell_locations(region_vc, Cells.locVC_cellTable)
|
||||
create_fly_locations(region_vc, Scouts.locVC_scoutTable)
|
||||
create_special_locations(region_vc, {k: Specials.loc_specialTable[k] for k in {105}})
|
||||
|
||||
region_sc = create_region(player, multiworld, Jak1Level.SPIDER_CAVE)
|
||||
create_cell_locations(region_sc, Cells.locSC_cellTable)
|
||||
|
||||
@@ -25,8 +25,11 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int)
|
||||
fj_fisherman = item_table[Specials.to_ap_id(5)]
|
||||
|
||||
sb_flut_flut = item_table[Specials.to_ap_id(17)]
|
||||
rv_pontoon_bridge = item_table[Specials.to_ap_id(33)]
|
||||
|
||||
sm_yellow_switch = item_table[Specials.to_ap_id(60)]
|
||||
sm_fort_gate = item_table[Specials.to_ap_id(63)]
|
||||
sm_gondola = item_table[Specials.to_ap_id(105)]
|
||||
|
||||
gmc_blue_sage = item_table[Specials.to_ap_id(71)]
|
||||
gmc_red_sage = item_table[Specials.to_ap_id(72)]
|
||||
@@ -96,39 +99,20 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int)
|
||||
Jak1Level.ROCK_VILLAGE,
|
||||
Jak1Level.PRECURSOR_BASIN)
|
||||
|
||||
# This is another virtual location that shares it's "borders" with its parent location.
|
||||
# You can do blue rings as soon as you finish purple rings.
|
||||
connect_region_to_sub(multiworld, player,
|
||||
Jak1Level.PRECURSOR_BASIN,
|
||||
Jak1SubLevel.PRECURSOR_BASIN_BLUE_RINGS)
|
||||
|
||||
connect_regions(multiworld, player,
|
||||
Jak1Level.ROCK_VILLAGE,
|
||||
Jak1Level.LOST_PRECURSOR_CITY)
|
||||
|
||||
# This pontoon bridge locks out Boggy Swamp and Mountain Pass,
|
||||
# effectively making it required to complete the game.
|
||||
connect_region_to_sub(multiworld, player,
|
||||
Jak1Level.LOST_PRECURSOR_CITY,
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_SUNKEN_ROOM)
|
||||
Jak1Level.ROCK_VILLAGE,
|
||||
Jak1SubLevel.ROCK_VILLAGE_PONTOON_BRIDGE,
|
||||
lambda state: state.has(rv_pontoon_bridge, player))
|
||||
|
||||
connect_subregions(multiworld, player,
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_SUNKEN_ROOM,
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_HELIX_ROOM)
|
||||
|
||||
# LPC is such a mess logistically... once you complete the climb up the helix room,
|
||||
# you are back to the room before the first slide, which is still the "main area" of LPC.
|
||||
connect_sub_to_region(multiworld, player,
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_HELIX_ROOM,
|
||||
Jak1Level.LOST_PRECURSOR_CITY)
|
||||
|
||||
# Once you raise the sunken room to the surface, you can access Rock Village directly.
|
||||
# You just need to complete the Location check to do this, you don't need to receive the power cell Item.
|
||||
connect_sub_to_region(multiworld, player,
|
||||
Jak1SubLevel.LOST_PRECURSOR_CITY_SUNKEN_ROOM,
|
||||
Jak1Level.ROCK_VILLAGE)
|
||||
|
||||
connect_regions(multiworld, player,
|
||||
Jak1Level.ROCK_VILLAGE,
|
||||
Jak1Level.BOGGY_SWAMP)
|
||||
Jak1SubLevel.ROCK_VILLAGE_PONTOON_BRIDGE,
|
||||
Jak1Level.BOGGY_SWAMP)
|
||||
|
||||
# Flut Flut only has one landing pad here, so leaving this subregion is as easy
|
||||
# as dismounting Flut Flut right where you found her.
|
||||
@@ -137,36 +121,30 @@ def set_rules(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int)
|
||||
Jak1SubLevel.BOGGY_SWAMP_FLUT_FLUT,
|
||||
lambda state: state.has(sb_flut_flut, player))
|
||||
|
||||
# Klaww is considered the "main area" of MP, and the "race" is a subregion.
|
||||
# It's not really intended to get back up the ledge overlooking Klaww's lava pit.
|
||||
connect_regions(multiworld, player,
|
||||
Jak1Level.ROCK_VILLAGE,
|
||||
Jak1Level.MOUNTAIN_PASS,
|
||||
lambda state: state.has(power_cell, player, 45))
|
||||
connect_sub_to_region(multiworld, player,
|
||||
Jak1SubLevel.ROCK_VILLAGE_PONTOON_BRIDGE,
|
||||
Jak1Level.MOUNTAIN_PASS,
|
||||
lambda state: state.has(power_cell, player, 45))
|
||||
|
||||
connect_region_to_sub(multiworld, player,
|
||||
Jak1Level.MOUNTAIN_PASS,
|
||||
Jak1SubLevel.MOUNTAIN_PASS_RACE)
|
||||
Jak1SubLevel.MOUNTAIN_PASS_SHORTCUT,
|
||||
lambda state: state.has(sm_yellow_switch, player))
|
||||
|
||||
connect_subregions(multiworld, player,
|
||||
Jak1SubLevel.MOUNTAIN_PASS_RACE,
|
||||
Jak1SubLevel.MOUNTAIN_PASS_SHORTCUT,
|
||||
lambda state: state.has(sm_yellow_switch, player))
|
||||
|
||||
connect_sub_to_region(multiworld, player,
|
||||
Jak1SubLevel.MOUNTAIN_PASS_RACE,
|
||||
Jak1Level.VOLCANIC_CRATER)
|
||||
connect_regions(multiworld, player,
|
||||
Jak1Level.MOUNTAIN_PASS,
|
||||
Jak1Level.VOLCANIC_CRATER)
|
||||
set_trade_requirements(multiworld, player, Jak1Level.VOLCANIC_CRATER, vc_traders, 1530)
|
||||
|
||||
connect_regions(multiworld, player,
|
||||
Jak1Level.VOLCANIC_CRATER,
|
||||
Jak1Level.SPIDER_CAVE)
|
||||
|
||||
# TODO - Yeah, this is a weird one. You technically need either 71 power cells OR
|
||||
# any 2 power cells after arriving at Volcanic Crater. Not sure how to model this...
|
||||
# Custom-added unlock for snowy mountain's gondola.
|
||||
connect_regions(multiworld, player,
|
||||
Jak1Level.VOLCANIC_CRATER,
|
||||
Jak1Level.SNOWY_MOUNTAIN)
|
||||
Jak1Level.SNOWY_MOUNTAIN,
|
||||
lambda state: state.has(sm_gondola, player))
|
||||
|
||||
connect_region_to_sub(multiworld, player,
|
||||
Jak1Level.SNOWY_MOUNTAIN,
|
||||
|
||||
@@ -16,10 +16,10 @@ from worlds.LauncherComponents import components, Component, launch_subprocess,
|
||||
|
||||
class JakAndDaxterSettings(settings.Group):
|
||||
class RootDirectory(settings.UserFolderPath):
|
||||
"""Path to folder containing the ArchipelaGOAL mod."""
|
||||
"""Path to folder containing the ArchipelaGOAL mod executables (gk.exe and goalc.exe)."""
|
||||
description = "ArchipelaGOAL Root Directory"
|
||||
|
||||
root_directory: RootDirectory = RootDirectory("D:/Files/Repositories/ArchipelaGOAL")
|
||||
root_directory: RootDirectory = RootDirectory("D:/Files/Repositories/ArchipelaGOAL/out/build/Release/bin")
|
||||
|
||||
|
||||
class JakAndDaxterWebWorld(WebWorld):
|
||||
|
||||
@@ -5,52 +5,82 @@
|
||||
The [Player Options Page](../player-options) for this game contains
|
||||
all the options you need to configure and export a config file.
|
||||
|
||||
At this time, Scout Flies are always randomized, and Precursor Orbs
|
||||
are never randomized.
|
||||
At this time, there are several caveats and restrictions:
|
||||
- Power Cells and Scout Flies are **always** randomized.
|
||||
- Precursor Orbs are **never** randomized.
|
||||
- **All** of the traders in the game become in-logic checks **if and only if** you have enough Orbs (1530) to pay them all at once.
|
||||
- This is to prevent hard locks, where an item required for progression is locked behind a trade you can't afford.
|
||||
|
||||
## What does randomization do to this game?
|
||||
All 101 Power Cells and 112 Scout Flies are now Location Checks
|
||||
and may contain Items for different games, as well as different Items from within Jak and Daxter.
|
||||
All 101 Power Cells and 112 Scout Flies are now Location Checks and may contain Items for different games,
|
||||
as well as different Items from within Jak and Daxter. Additionally, several special checks and corresponding items
|
||||
have been added that are required to complete the game.
|
||||
|
||||
## What are the special checks and how do I check them?
|
||||
| Check Name | How To Check |
|
||||
|------------------------|------------------------------------------------------------------------------|
|
||||
| Fisherman's Boat | Complete the fishing minigame in Forbidden Jungle |
|
||||
| Jungle Elevator | Collect the power cell at the top of the temple in Forbidden Jungle |
|
||||
| Blue Eco Switch | Collect the power cell on the blue vent switch in Forbidden Jungle |
|
||||
| Flut Flut | Push the egg off the cliff in Sentinel Beach and talk to the bird lady |
|
||||
| Warrior's Pontoons | Talk to the Warrior in Rock Village once (you do NOT have to trade with him) |
|
||||
| Snowy Mountain Gondola | Approach the gondola in Volcanic Crater |
|
||||
| Yellow Eco Switch | Collect the power cell on the yellow vent switch in Snowy Mountain |
|
||||
| Snowy Fort Gate | Ride the Flut Flut in Snowy Mountain and press the fort gate switch |
|
||||
| Freed The Blue Sage | Free the Blue Sage in Gol and Maia's Citadel |
|
||||
| Freed The Red Sage | Free the Red Sage in Gol and Maia's Citadel |
|
||||
| Freed The Yellow Sage | Free the Yellow Sage in Gol and Maia's Citadel |
|
||||
| Freed The Green Sage | Free the Green Sage in Gol and Maia's Citadel |
|
||||
|
||||
## What are the special items and what do they unlock?
|
||||
| Item Name | What It Unlocks |
|
||||
|--------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
|
||||
| Fisherman's Boat | Misty Island |
|
||||
| Jungle Elevator | The blue vent switch inside the temple in Forbidden Jungle |
|
||||
| Blue Eco Switch | The plant boss inside the temple in Forbidden Jungle <br/> The cannon tower in Sentinel Beach |
|
||||
| Flut Flut | The upper platforms in Boggy Swamp <br/> The fort gate switch in Snowy Mountain |
|
||||
| Warrior's Pontoons | Boggy Swamp and Mountain Pass |
|
||||
| Snowy Mountain Gondola | Snowy Mountain |
|
||||
| Yellow Eco Switch | The frozen box in Snowy Mountain <br/> The shortcut in Mountain Pass |
|
||||
| Snowy Fort Gate | The fort in Snowy Mountain |
|
||||
| Freed The Blue Sage <br/> Freed The Red Sage <br/> Freed The Yellow Sage | The final staircase in Gol and Maia's Citadel |
|
||||
| Freed The Green Sage | The final elevator in Gol and Maia's Citadel |
|
||||
|
||||
## What is the goal of the game once randomized?
|
||||
To complete the game, you must defeat the Gol and Maia and stop them from opening the Dark Eco silo.
|
||||
|
||||
In order to reach them, you will need at least 72 Power Cells to cross the Lava Tube. In addition,
|
||||
you will need the four specific Power Cells obtained by freeing the Red, Blue, Yellow, and Green Sages.
|
||||
you will need the four special items that free the Red, Blue, Yellow, and Green Sages.
|
||||
|
||||
## How do I progress through the game?
|
||||
You can progress by performing tasks and completing the challenges that would normally give you Power Cells and
|
||||
Scout Flies in the game. If you are playing with others, those players may find Power Cells and Scout Flies
|
||||
in their games, and those Items will be automatically sent to your game.
|
||||
## What happens when I pick up or receive a power cell?
|
||||
When you pick up a power cell, Jak and Daxter will perform their victory animation. Your power cell count will
|
||||
NOT change. The pause menu will say "Task Completed" below the picked-up Power Cell. If your power cell was related
|
||||
to one of the special checks listed above, you will automatically check that location as well - a 2 for 1 deal!
|
||||
Finally, your text client will inform you what you found and who it belongs to.
|
||||
|
||||
If you have completed all possible tasks available to you but still cannot progress, you may have to wait for
|
||||
another player to find enough of your game's Items to allow you to progress. If that does not apply,
|
||||
double-check your spoiler log to make sure you have all the items you should have. If you don't,
|
||||
you may have encountered a bug. Please see the options for bug reporting below.
|
||||
When you receive a power cell, your power cell count will tick up by 1. Gameplay will otherwise continue as normal.
|
||||
Finally, your text client will inform you where you received the power cell from.
|
||||
|
||||
## What happens when I pick up an item?
|
||||
Jak and Daxter will perform their victory animation, if applicable. You will not receive that item, and
|
||||
the Item count for that item will not change. The pause menu will say "Task Completed" below the
|
||||
picked-up Power Cell, but the icon will remain "dormant." You will see a message in your text client saying
|
||||
what you found and who it belongs to.
|
||||
## What happens when I pick up or receive a scout fly?
|
||||
When you pick up a scout fly, your scout fly count will NOT change. The pause menu will show you the number of
|
||||
scout flies you picked up per-region, and this number will have ticked up by 1 for the region that scout fly belongs to.
|
||||
Finally, your text client will inform you what you found and who it belongs to.
|
||||
|
||||
## What happens when I receive an item?
|
||||
Jak and Daxter won't perform their victory animation, and gameplay will continue as normal. Your text client will
|
||||
inform you where you received the Item from, and which one it is. Your Item count for that type of Item will also
|
||||
tick up. The pause menu will not say "Task Completed" below the selected Power Cell, but the icon will be "activated."
|
||||
When you receive a scout fly, your total scout fly count will tick up by 1. The pause menu will show you the number of
|
||||
scout flies you received per-region, and this number will have ticked up by 1 for the region that scout fly belongs to.
|
||||
Finally, your text client will inform you where you received the scout fly from, and which one it is.
|
||||
|
||||
## I can't reach a certain area within an accessible region, how do I get there?
|
||||
Some areas are locked behind possession of specific Power Cells. For example, you cannot access Misty Island
|
||||
until you have the "Catch 200 Pounds of Fish" Power Cell. Keep in mind, your access to Misty Island is determined
|
||||
_through possession of this specific Power Cell only,_ **not** _by you completing the Fishing minigame._
|
||||
## How do I check the "Free 7 Scout Flies" power cell?
|
||||
You will automatically check this power cell when you _receive_ your 7th scout fly, NOT when you _pick up_ your 7th
|
||||
scout fly. So in short:
|
||||
|
||||
- When you _pick up_ your 7th fly, the normal rules apply.
|
||||
- When you _receive_ your 7th fly, 2 things will happen in quick succession.
|
||||
- First, you will receive that scout fly, as normal.
|
||||
- Second, you will immediately complete the "Free 7 Scout Flies" check, which will send out another item.
|
||||
|
||||
## I got soft-locked and can't leave, how do I get out of here?
|
||||
As stated before, some areas are locked behind possession of specific Power Cells. But you may already be past
|
||||
a point-of-no-return preventing you from backtracking. One example is the Forbidden Jungle temple, where
|
||||
the elevator is locked at the bottom, and if you haven't unlocked the Blue Eco Switch, you cannot access
|
||||
the Plant Boss's room and escape.
|
||||
|
||||
In this scenario, you will need to open your menu and find the "Warp To Home" option at the bottom of the list.
|
||||
Open the game's menu, navigate to Options, and find the "Warp To Home" option at the bottom of the list.
|
||||
Selecting this option will instantly teleport you to Geyser Rock. From there, you can teleport back to the nearest
|
||||
sage's hut to continue your journey.
|
||||
|
||||
@@ -60,8 +90,7 @@ Depending on the nature of the bug, there are a couple of different options.
|
||||
* If you found a logical error in the randomizer, please create a new Issue
|
||||
[here.](https://github.com/ArchipelaGOAL/Archipelago/issues)
|
||||
* Use this page if:
|
||||
* You are hard-locked from progressing. For example, you are stuck on Geyser Rock because one of the four
|
||||
Geyser Rock Power Cells is not on Geyser Rock.
|
||||
* An item required for progression is unreachable.
|
||||
* The randomizer did not respect one of the Options you chose.
|
||||
* You see a mistake, typo, etc. on this webpage.
|
||||
* You see an error or stack trace appear on the text client.
|
||||
@@ -70,7 +99,7 @@ Depending on the nature of the bug, there are a couple of different options.
|
||||
* If you encountered an error in OpenGOAL, please create a new Issue
|
||||
[here.](https://github.com/ArchipelaGOAL/ArchipelaGOAL/issues)
|
||||
* Use this page if:
|
||||
* You encounter a crash, freeze, reset, etc.
|
||||
* You encounter a crash, freeze, reset, etc in the game.
|
||||
* You fail to send Items you find in the game to the Archipelago server.
|
||||
* You fail to receive Items the server sends to you.
|
||||
* Your game disconnects from the server and cannot reconnect.
|
||||
|
||||
@@ -38,6 +38,8 @@ loc_specialTable = {
|
||||
4: "Jungle Elevator",
|
||||
2: "Blue Eco Switch",
|
||||
17: "Flut Flut",
|
||||
33: "Warrior's Pontoons",
|
||||
105: "Snowy Mountain Gondola",
|
||||
60: "Yellow Eco Switch",
|
||||
63: "Snowy Fort Gate",
|
||||
71: "Freed The Blue Sage",
|
||||
|
||||
Reference in New Issue
Block a user