mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-24 18:03:19 -07:00
Make orb trade amounts configurable, make orbsanity defaults more reasonable.
This commit is contained in:
@@ -130,6 +130,8 @@ class JakAndDaxterContext(CommonContext):
|
||||
slot_data["fire_canyon_cell_count"],
|
||||
slot_data["mountain_pass_cell_count"],
|
||||
slot_data["lava_tube_cell_count"],
|
||||
slot_data["citizen_orb_trade_amount"],
|
||||
slot_data["oracle_orb_trade_amount"],
|
||||
goal_id))
|
||||
|
||||
# Because Orbsanity and the orb traders in the game are intrinsically linked, we need the server
|
||||
|
||||
@@ -3,8 +3,8 @@ from Options import PerGameCommonOptions, StartInventoryPool, Toggle, Choice, Ra
|
||||
|
||||
|
||||
class EnableMoveRandomizer(Toggle):
|
||||
"""Enable to include movement options as items in the randomizer. Jak is only able to run, swim, and single jump
|
||||
until you find his other moves.
|
||||
"""Enable to include movement options as items in the randomizer. Until you find his other moves, Jak is limited to
|
||||
running, swimming, single-jumping, and shooting yellow eco through his goggles.
|
||||
|
||||
This adds 11 items to the pool."""
|
||||
display_name = "Enable Move Randomizer"
|
||||
@@ -51,7 +51,7 @@ class GlobalOrbsanityBundleSize(Choice):
|
||||
option_500_orbs = 500
|
||||
option_1000_orbs = 1000
|
||||
option_2000_orbs = 2000
|
||||
default = 1
|
||||
default = 20
|
||||
|
||||
|
||||
class PerLevelOrbsanityBundleSize(Choice):
|
||||
@@ -64,11 +64,11 @@ class PerLevelOrbsanityBundleSize(Choice):
|
||||
option_10_orbs = 10
|
||||
option_25_orbs = 25
|
||||
option_50_orbs = 50
|
||||
default = 1
|
||||
default = 25
|
||||
|
||||
|
||||
class FireCanyonCellCount(Range):
|
||||
"""Set the number of orbs you need to cross Fire Canyon."""
|
||||
"""Set the number of power cells you need to cross Fire Canyon."""
|
||||
display_name = "Fire Canyon Cell Count"
|
||||
range_start = 0
|
||||
range_end = 100
|
||||
@@ -76,7 +76,7 @@ class FireCanyonCellCount(Range):
|
||||
|
||||
|
||||
class MountainPassCellCount(Range):
|
||||
"""Set the number of orbs you need to reach Klaww and cross Mountain Pass."""
|
||||
"""Set the number of power cells you need to reach Klaww and cross Mountain Pass."""
|
||||
display_name = "Mountain Pass Cell Count"
|
||||
range_start = 0
|
||||
range_end = 100
|
||||
@@ -84,13 +84,35 @@ class MountainPassCellCount(Range):
|
||||
|
||||
|
||||
class LavaTubeCellCount(Range):
|
||||
"""Set the number of orbs you need to cross Lava Tube."""
|
||||
"""Set the number of power cells you need to cross Lava Tube."""
|
||||
display_name = "Lava Tube Cell Count"
|
||||
range_start = 0
|
||||
range_end = 100
|
||||
default = 72
|
||||
|
||||
|
||||
# 222 is the maximum because there are 9 citizen trades and 2000 orbs to trade (2000/9 = 222).
|
||||
class CitizenOrbTradeAmount(Range):
|
||||
"""Set the number of orbs you need to trade to ordinary citizens for a power cell (Mayor, Uncle, etc.).
|
||||
|
||||
Along with Oracle Orb Trade Amount, this setting cannot exceed the total number of orbs in the game (2000)."""
|
||||
display_name = "Citizen Orb Trade Amount"
|
||||
range_start = 0
|
||||
range_end = 222
|
||||
default = 90
|
||||
|
||||
|
||||
# 333 is the maximum because there are 6 oracle trades and 2000 orbs to trade (2000/6 = 333).
|
||||
class OracleOrbTradeAmount(Range):
|
||||
"""Set the number of orbs you need to trade to the Oracles for a power cell.
|
||||
|
||||
Along with Citizen Orb Trade Amount, this setting cannot exceed the total number of orbs in the game (2000)."""
|
||||
display_name = "Oracle Orb Trade Amount"
|
||||
range_start = 0
|
||||
range_end = 333
|
||||
default = 120
|
||||
|
||||
|
||||
class CompletionCondition(Choice):
|
||||
"""Set the goal for completing the game."""
|
||||
display_name = "Completion Condition"
|
||||
@@ -113,5 +135,7 @@ class JakAndDaxterOptions(PerGameCommonOptions):
|
||||
fire_canyon_cell_count: FireCanyonCellCount
|
||||
mountain_pass_cell_count: MountainPassCellCount
|
||||
lava_tube_cell_count: LavaTubeCellCount
|
||||
citizen_orb_trade_amount: CitizenOrbTradeAmount
|
||||
oracle_orb_trade_amount: OracleOrbTradeAmount
|
||||
jak_completion_condition: CompletionCondition
|
||||
start_inventory_from_pool: StartInventoryPool
|
||||
|
||||
@@ -133,6 +133,9 @@ def create_regions(multiworld: MultiWorld, options: JakAndDaxterOptions, player:
|
||||
# the connector levels. E.g. if you set Fire Canyon count to 99, we may not have 99 Locations in hub 1.
|
||||
verify_connector_level_accessibility(multiworld, options, player)
|
||||
|
||||
# Also verify that we didn't overload the trade amounts with more orbs than exist in the world.
|
||||
verify_orbs_for_trades(multiworld, options, player)
|
||||
|
||||
|
||||
def verify_connector_level_accessibility(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int):
|
||||
|
||||
@@ -182,3 +185,26 @@ def verify_connector_level_accessibility(multiworld: MultiWorld, options: JakAnd
|
||||
|
||||
for item in required_items:
|
||||
state.collect(JakAndDaxterItem(required_items[item], ItemClassification.progression, item, player))
|
||||
|
||||
|
||||
def verify_orbs_for_trades(multiworld: MultiWorld, options: JakAndDaxterOptions, player: int):
|
||||
|
||||
citizen_trade_orbs = 9 * options.citizen_orb_trade_amount
|
||||
if citizen_trade_orbs > 2000:
|
||||
raise OptionError(f"Settings conflict with {options.citizen_orb_trade_amount.display_name}: "
|
||||
f"required number of orbs to trade with citizens ({citizen_trade_orbs}) "
|
||||
f"is more than all the orbs in the game (2000).")
|
||||
|
||||
oracle_trade_orbs = 6 * options.oracle_orb_trade_amount
|
||||
if oracle_trade_orbs > 2000:
|
||||
raise OptionError(f"Settings conflict with {options.oracle_orb_trade_amount.display_name}: "
|
||||
f"required number of orbs to trade with oracles ({oracle_trade_orbs}) "
|
||||
f"is more than all the orbs in the game (2000).")
|
||||
|
||||
total_trade_orbs = (9 * options.citizen_orb_trade_amount) + (6 * options.oracle_orb_trade_amount)
|
||||
if total_trade_orbs > 2000:
|
||||
raise OptionError(f"Settings conflict with Orb Trade Amounts: "
|
||||
f"required number of orbs for all trades ({total_trade_orbs}) "
|
||||
f"is more than all the orbs in the game (2000). "
|
||||
f"Reduce the value of either {options.citizen_orb_trade_amount.display_name} "
|
||||
f"or {options.oracle_orb_trade_amount.display_name}.")
|
||||
|
||||
@@ -200,4 +200,6 @@ class JakAndDaxterWorld(World):
|
||||
"fire_canyon_cell_count",
|
||||
"mountain_pass_cell_count",
|
||||
"lava_tube_cell_count",
|
||||
"citizen_orb_trade_amount",
|
||||
"oracle_orb_trade_amount",
|
||||
"jak_completion_condition")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import random
|
||||
import struct
|
||||
from typing import ByteString, List, Callable
|
||||
import json
|
||||
import pymem
|
||||
@@ -76,6 +77,8 @@ collected_bundle_offset = offsets.define(sizeof_uint32, 17)
|
||||
fire_canyon_unlock_offset = offsets.define(sizeof_float)
|
||||
mountain_pass_unlock_offset = offsets.define(sizeof_float)
|
||||
lava_tube_unlock_offset = offsets.define(sizeof_float)
|
||||
citizen_orb_amount_offset = offsets.define(sizeof_float)
|
||||
oracle_orb_amount_offset = offsets.define(sizeof_float)
|
||||
completion_goal_offset = offsets.define(sizeof_uint8)
|
||||
completed_offset = offsets.define(sizeof_uint8)
|
||||
|
||||
@@ -89,6 +92,11 @@ my_item_finder_offset = offsets.define(sizeof_uint8, 32)
|
||||
end_marker_offset = offsets.define(sizeof_uint8, 4)
|
||||
|
||||
|
||||
# Can't believe this is easier to do in GOAL than Python but that's how it be sometimes.
|
||||
def as_float(value: int) -> int:
|
||||
return int(struct.unpack('f', value.to_bytes(sizeof_float, "little"))[0])
|
||||
|
||||
|
||||
# "Jak" to be replaced by player name in the Client.
|
||||
def autopsy(died: int) -> str:
|
||||
assert died > 0, f"Tried to find Jak's cause of death, but he's still alive!"
|
||||
@@ -239,10 +247,11 @@ class JakAndDaxterMemoryReader:
|
||||
|
||||
def read_memory(self) -> List[int]:
|
||||
try:
|
||||
next_cell_index = self.read_goal_address(0, sizeof_uint64)
|
||||
next_buzzer_index = self.read_goal_address(next_buzzer_index_offset, sizeof_uint64)
|
||||
next_special_index = self.read_goal_address(next_special_index_offset, sizeof_uint64)
|
||||
# Need to grab these first and convert to floats, see below.
|
||||
citizen_orb_amount = self.read_goal_address(citizen_orb_amount_offset, sizeof_float)
|
||||
oracle_orb_amount = self.read_goal_address(oracle_orb_amount_offset, sizeof_float)
|
||||
|
||||
next_cell_index = self.read_goal_address(next_cell_index_offset, sizeof_uint64)
|
||||
for k in range(0, next_cell_index):
|
||||
next_cell = self.read_goal_address(cells_checked_offset + (k * sizeof_uint32), sizeof_uint32)
|
||||
cell_ap_id = Cells.to_ap_id(next_cell)
|
||||
@@ -253,13 +262,16 @@ class JakAndDaxterMemoryReader:
|
||||
# If orbsanity is ON and next_cell is one of the traders or oracles, then run a callback
|
||||
# to add their amount to the DataStorage value holding our current orb trade total.
|
||||
if next_cell in {11, 12, 31, 32, 33, 96, 97, 98, 99}:
|
||||
self.orbs_paid += 90
|
||||
logger.debug("Traded 90 orbs!")
|
||||
citizen_orb_amount = as_float(citizen_orb_amount)
|
||||
self.orbs_paid += citizen_orb_amount
|
||||
logger.debug(f"Traded {citizen_orb_amount} orbs!")
|
||||
|
||||
if next_cell in {13, 14, 34, 35, 100, 101}:
|
||||
self.orbs_paid += 120
|
||||
logger.debug("Traded 120 orbs!")
|
||||
oracle_orb_amount = as_float(oracle_orb_amount)
|
||||
self.orbs_paid += oracle_orb_amount
|
||||
logger.debug(f"Traded {oracle_orb_amount} orbs!")
|
||||
|
||||
next_buzzer_index = self.read_goal_address(next_buzzer_index_offset, sizeof_uint64)
|
||||
for k in range(0, next_buzzer_index):
|
||||
next_buzzer = self.read_goal_address(buzzers_checked_offset + (k * sizeof_uint32), sizeof_uint32)
|
||||
buzzer_ap_id = Flies.to_ap_id(next_buzzer)
|
||||
@@ -267,6 +279,7 @@ class JakAndDaxterMemoryReader:
|
||||
self.location_outbox.append(buzzer_ap_id)
|
||||
logger.debug("Checked scout fly: " + str(next_buzzer))
|
||||
|
||||
next_special_index = self.read_goal_address(next_special_index_offset, sizeof_uint64)
|
||||
for k in range(0, next_special_index):
|
||||
next_special = self.read_goal_address(specials_checked_offset + (k * sizeof_uint32), sizeof_uint32)
|
||||
special_ap_id = Specials.to_ap_id(next_special)
|
||||
@@ -284,7 +297,6 @@ class JakAndDaxterMemoryReader:
|
||||
self.deathlink_enabled = bool(deathlink_flag)
|
||||
|
||||
next_cache_index = self.read_goal_address(next_orb_cache_index_offset, sizeof_uint64)
|
||||
|
||||
for k in range(0, next_cache_index):
|
||||
next_cache = self.read_goal_address(orb_caches_checked_offset + (k * sizeof_uint32), sizeof_uint32)
|
||||
cache_ap_id = Caches.to_ap_id(next_cache)
|
||||
|
||||
@@ -356,15 +356,18 @@ class JakAndDaxterReplClient:
|
||||
async def setup_options(self,
|
||||
os_option: int, os_bundle: int,
|
||||
fc_count: int, mp_count: int,
|
||||
lt_count: int, goal_id: int) -> bool:
|
||||
lt_count: int, ct_amount: int,
|
||||
ot_amount: int, goal_id: int) -> bool:
|
||||
ok = await self.send_form(f"(ap-setup-options! "
|
||||
f"(the uint {os_option}) (the uint {os_bundle}) "
|
||||
f"(the float {fc_count}) (the float {mp_count}) "
|
||||
f"(the float {lt_count}) (the uint {goal_id}))")
|
||||
f"(the float {lt_count}) (the float {ct_amount}) "
|
||||
f"(the float {ot_amount}) (the uint {goal_id}))")
|
||||
message = (f"Setting options: \n"
|
||||
f" Orbsanity Option {os_option}, Orbsanity Bundle {os_bundle}, \n"
|
||||
f" FC Cell Count {fc_count}, MP Cell Count {mp_count}, \n"
|
||||
f" LT Cell Count {lt_count}, Completion GOAL {goal_id}... ")
|
||||
f" LT Cell Count {lt_count}, Citizen Orb Amt {ct_amount}, \n"
|
||||
f" Oracle Orb Amt {ot_amount}, Completion GOAL {goal_id}... ")
|
||||
if ok:
|
||||
logger.debug(message + "Success!")
|
||||
else:
|
||||
|
||||
@@ -7,9 +7,9 @@ all the options you need to configure and export a config file.
|
||||
|
||||
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.
|
||||
- **All** the traders in the game become in-logic checks **if and only if** you have enough Orbs to pay all of them at once.
|
||||
- This is to prevent hard locks, where an item required for progression is locked behind a trade you can't afford because you spent the orbs elsewhere.
|
||||
- By default, that total is 1530.
|
||||
|
||||
## What does randomization do to this game?
|
||||
The game now contains the following Location checks:
|
||||
@@ -56,10 +56,14 @@ This will show you a list of all the special items in the game, ones not normall
|
||||
Gray items indicate you do not possess that item, light blue items indicate you possess that item.
|
||||
|
||||
## 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.
|
||||
By default, 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, as well as the four special items for
|
||||
freeing the Red, Blue, Yellow, and Green Sages.
|
||||
|
||||
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 special items that free the Red, Blue, Yellow, and Green Sages.
|
||||
Alternatively, you can choose from a handful of other completion conditions like defeating a particular boss, crossing
|
||||
a particular connector level, or opening the 100 Power Cell door after defeating the final boss. You can also customize
|
||||
the thresholds for connector levels and orb trades. These options allow you to tailor the expected length and difficulty
|
||||
of your run as you see fit.
|
||||
|
||||
## 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
|
||||
@@ -85,23 +89,23 @@ 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.
|
||||
- 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.
|
||||
|
||||
## What does Deathlink do?
|
||||
If you enable Deathlink, all the other players in your Multiworld who also have it enabled will be linked on death.
|
||||
That means when Jak dies in your game, the players in your Deathlink group also die. Likewise, if any of the other
|
||||
players die, Jak will also die in a random fashion.
|
||||
players die, Jak will also die in a random, possibly spectacular fashion.
|
||||
|
||||
You can turn off Deathlink at any time in the game by opening the game's menu, navigate to `Options`,
|
||||
You can turn off Deathlink at any time in the game by opening the game's menu and navigating to `Options`,
|
||||
then `Archipelago Options`, then `Deathlink`.
|
||||
|
||||
## What does Move Randomizer do?
|
||||
If you enable Move Randomizer, most of Jak's movement set will be added to the randomized item pool, and you will need
|
||||
to receive the move in order to use it (i.e. you must find it, or another player must send it to you). Some moves have
|
||||
prerequisite moves that you must also have in order to use them (e.g. Crouch Jump is dependent on Crouch). Jak will only
|
||||
be able to run, swim (including underwater), and perform single jumps. Note that Flut Flut will have access to her full
|
||||
movement set at all times.
|
||||
be able to run, swim (including underwater), perform single jumps, and shoot yellow eco from his goggles ("firing from
|
||||
the hip" requires Punch). Note that Flut Flut and the Zoomer will have access to their full movement sets at all times.
|
||||
|
||||
You can turn off Move Rando at any time in the game by opening the game's menu, navigate to `Options`,
|
||||
then `Archipelago Options`, then `Move Randomizer`. This will give you access to the full movement set again.
|
||||
@@ -134,9 +138,9 @@ a "bundle" of the correct number of orbs, you will trigger the next release in t
|
||||
will be added to the item pool to be randomized. There are several options to change the difficulty of this challenge.
|
||||
|
||||
- "Per Level" Orbsanity means the lists of orb checks are generated and populated for each level in the game.
|
||||
- (Geyser Rock, Sandover Village, etc.)
|
||||
- (Geyser Rock, Sandover Village, etc.)
|
||||
- "Global" Orbsanity means there is only one list of checks for the entire game.
|
||||
- It does not matter where you pick up the orbs, they all count toward the same list.
|
||||
- It does not matter where you pick up the orbs, they all count toward the same list.
|
||||
- The options with "Bundle Size" in the name indicate how many orbs are in a "bundle." This adds a number of Items
|
||||
and Locations to the pool inversely proportional to the size of the bundle.
|
||||
- For example, if your bundle size is 20 orbs, you will add 100 items to the pool. If your bundle size is 250 orbs,
|
||||
@@ -161,20 +165,18 @@ to the nearest sage's hut to continue your journey.
|
||||
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:
|
||||
[here.](https://github.com/ArchipelaGOAL/Archipelago/issues) Use this page if:
|
||||
* 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.
|
||||
* Please upload your config file and spoiler log file in the Issue, so we can troubleshoot the problem.
|
||||
|
||||
* 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 in the game.
|
||||
[here.](https://github.com/ArchipelaGOAL/ArchipelaGOAL/issues) Use this page if:
|
||||
* 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.
|
||||
* You go looking for a game item that has already disappeared before you could reach it.
|
||||
* Please upload any log files that may have been generated.
|
||||
|
||||
* Please upload your config file, spoiler log file, and any other generated logs in the Issue, so we can troubleshoot the problem.
|
||||
@@ -14,7 +14,7 @@ class JakAndDaxterRegion(Region):
|
||||
"""
|
||||
Holds region information such as name, level name, number of orbs available, etc.
|
||||
We especially need orb counts to be tracked because we need to know when you can
|
||||
afford the 90-orb and 120-orb payments for more checks.
|
||||
afford the Citizen and Oracle orb payments for more checks.
|
||||
"""
|
||||
game: str = jak1_name
|
||||
level_name: str
|
||||
|
||||
@@ -7,18 +7,20 @@ from ..Rules import can_free_scout_flies, can_trade, can_reach_orbs
|
||||
|
||||
def build_regions(level_name: str, multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) -> List[JakAndDaxterRegion]:
|
||||
|
||||
total_trade_orbs = (9 * options.citizen_orb_trade_amount) + (6 * options.oracle_orb_trade_amount)
|
||||
|
||||
# This includes most of the area surrounding LPC as well, for orb_count purposes. You can swim and single jump.
|
||||
main_area = JakAndDaxterRegion("Main Area", player, multiworld, level_name, 23)
|
||||
main_area.add_cell_locations([31], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([32], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([33], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([34], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([35], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530, 34))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs, 34))
|
||||
|
||||
# These 2 scout fly boxes can be broken by running with nearby blue eco.
|
||||
main_area.add_fly_locations([196684, 262220])
|
||||
|
||||
@@ -7,14 +7,16 @@ from ..Rules import can_free_scout_flies, can_trade, can_reach_orbs
|
||||
|
||||
def build_regions(level_name: str, multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) -> List[JakAndDaxterRegion]:
|
||||
|
||||
total_trade_orbs = (9 * options.citizen_orb_trade_amount) + (6 * options.oracle_orb_trade_amount)
|
||||
|
||||
main_area = JakAndDaxterRegion("Main Area", player, multiworld, level_name, 26)
|
||||
|
||||
# Yakows requires no combat.
|
||||
main_area.add_cell_locations([10])
|
||||
main_area.add_cell_locations([11], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([12], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
|
||||
# These 4 scout fly boxes can be broken by running with all the blue eco from Sentinel Beach.
|
||||
main_area.add_fly_locations([262219, 327755, 131147, 65611])
|
||||
@@ -33,9 +35,9 @@ def build_regions(level_name: str, multiworld: MultiWorld, options: JakAndDaxter
|
||||
|
||||
oracle_platforms = JakAndDaxterRegion("Oracle Platforms", player, multiworld, level_name, 6)
|
||||
oracle_platforms.add_cell_locations([13], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
oracle_platforms.add_cell_locations([14], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530, 13))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs, 13))
|
||||
oracle_platforms.add_fly_locations([393291], access_rule=lambda state:
|
||||
can_free_scout_flies(state, player))
|
||||
|
||||
|
||||
@@ -8,20 +8,22 @@ from ..locs import CellLocations as Cells, ScoutLocations as Scouts
|
||||
|
||||
def build_regions(level_name: str, multiworld: MultiWorld, options: JakAndDaxterOptions, player: int) -> List[JakAndDaxterRegion]:
|
||||
|
||||
total_trade_orbs = (9 * options.citizen_orb_trade_amount) + (6 * options.oracle_orb_trade_amount)
|
||||
|
||||
# No area is inaccessible in VC even with only running and jumping.
|
||||
main_area = JakAndDaxterRegion("Main Area", player, multiworld, level_name, 50)
|
||||
main_area.add_cell_locations([96], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([97], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530, 96))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs, 96))
|
||||
main_area.add_cell_locations([98], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530, 97))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs, 97))
|
||||
main_area.add_cell_locations([99], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530, 98))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs, 98))
|
||||
main_area.add_cell_locations([100], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs))
|
||||
main_area.add_cell_locations([101], access_rule=lambda state:
|
||||
can_trade(state, player, multiworld, options, 1530, 100))
|
||||
can_trade(state, player, multiworld, options, total_trade_orbs, 100))
|
||||
|
||||
# Hidden Power Cell: you can carry yellow eco from Spider Cave just by running and jumping
|
||||
# and using your Goggles to shoot the box (you do not need Punch to shoot from FP mode).
|
||||
|
||||
Reference in New Issue
Block a user