Added a host.yaml option to override friendly limits, plus a couple of code review updates.

This commit is contained in:
massimilianodelliubaldini
2024-08-27 16:23:28 -04:00
parent 746b281f48
commit 3eadf54bf3
6 changed files with 53 additions and 41 deletions

View File

@@ -107,6 +107,7 @@ class JakAndDaxterContext(CommonContext):
if password_requested and not self.password:
await super(JakAndDaxterContext, self).server_auth(password_requested)
await self.get_username()
self.tags = set()
await self.send_connect()
def on_package(self, cmd: str, args: dict):

View File

@@ -174,11 +174,10 @@ def enforce_multiplayer_limits(options: JakAndDaxterOptions):
f"{friendly_message}")
def verify_orb_trade_amounts(options: JakAndDaxterOptions):
def verify_orb_trade_amounts(world: JakAndDaxterWorld):
total_trade_orbs = (9 * options.citizen_orb_trade_amount) + (6 * options.oracle_orb_trade_amount)
if total_trade_orbs > 2000:
raise OptionError(f"Required number of orbs for all trades ({total_trade_orbs}) "
if world.total_trade_orbs > 2000:
raise OptionError(f"Required number of orbs for all trades ({world.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}.")
f"Reduce the value of either {world.options.citizen_orb_trade_amount.display_name} "
f"or {world.options.oracle_orb_trade_amount.display_name}.")

View File

@@ -1,8 +1,13 @@
from typing import Dict, Any, ClassVar, Tuple, Callable, Optional
from typing import Dict, Any, ClassVar, Tuple, Callable, Optional, Union
import Utils
import settings
from Utils import local_path
from BaseClasses import Item, ItemClassification, Tutorial, CollectionState
from BaseClasses import (Item,
ItemClassification as ItemClass,
Tutorial,
CollectionState)
from .GameID import jak1_id, jak1_name, jak1_max
from .JakAndDaxterOptions import JakAndDaxterOptions, EnableOrbsanity
from .Locations import (JakAndDaxterLocation,
@@ -48,7 +53,13 @@ class JakAndDaxterSettings(settings.Group):
Ensure this path contains forward slashes (/) only."""
description = "ArchipelaGOAL Root Directory"
class EnforceFriendlyOptions(settings.Bool):
"""Enforce friendly player options to be used in a multiplayer seed.
Disabling this allows for more disruptive and challenging options, but may impact seed generation."""
description = "ArchipelaGOAL Enforce Friendly Options"
root_directory: RootDirectory = RootDirectory("%appdata%/OpenGOAL-Mods/archipelagoal")
enforce_friendly_options: Union[EnforceFriendlyOptions, bool] = True
class JakAndDaxterWebWorld(WebWorld):
@@ -107,23 +118,27 @@ class JakAndDaxterWorld(World):
{11, 12, 31, 32, 33, 96, 97, 98, 99, 13, 14, 34, 35, 100, 101}},
}
# Functions and Variables that are Options-driven, keep them as instance variables here so that we don't clog up
# These functions and variables are Options-driven, keep them as instance variables here so that we don't clog up
# the seed generation routines with options checking. So we set these once, and then just use them as needed.
can_trade: Callable[[CollectionState, int, Optional[int]], bool]
orb_bundle_size: int = 0
orb_bundle_item_name: str = ""
orb_bundle_size: int = 0
total_trade_orbs: int = 0
# Handles various options validation, rules enforcement, and caching of important information.
def generate_early(self) -> None:
# For the fairness of other players in a multiworld game, enforce some friendly limitations on our options,
# so we don't cause chaos during seed generation. These friendly limits should **guarantee** a successful gen.
if self.multiworld.players > 1:
enforce_friendly_options = Utils.get_settings()["jakanddaxter_options"]["enforce_friendly_options"]
if self.multiworld.players > 1 and enforce_friendly_options:
from .Rules import enforce_multiplayer_limits
enforce_multiplayer_limits(self.options)
# Verify that we didn't overload the trade amounts with more orbs than exist in the world.
# This is easy to do by accident even in a single-player world.
self.total_trade_orbs = (9 * self.options.citizen_orb_trade_amount) + (6 * self.options.oracle_orb_trade_amount)
from .Rules import verify_orb_trade_amounts
verify_orb_trade_amounts(self.options)
verify_orb_trade_amounts(self)
# Cache the orb bundle size and item name for quicker reference.
if self.options.enable_orbsanity == EnableOrbsanity.option_per_level:
@@ -146,36 +161,39 @@ class JakAndDaxterWorld(World):
# visualize_regions(self.multiworld.get_region("Menu", self.player), "jakanddaxter.puml")
# Helper function to reuse some nasty if/else trees.
def item_type_helper(self, item) -> Tuple[int, ItemClassification]:
def item_type_helper(self, item) -> Tuple[int, ItemClass]:
# Make 101 Power Cells.
if item in range(jak1_id, jak1_id + Scouts.fly_offset):
classification = ItemClassification.progression_skip_balancing
classification = ItemClass.progression_skip_balancing
count = 101
# Make 7 Scout Flies per level.
elif item in range(jak1_id + Scouts.fly_offset, jak1_id + Specials.special_offset):
classification = ItemClassification.progression_skip_balancing
classification = ItemClass.progression_skip_balancing
count = 7
# Make only 1 of each Special Item.
elif item in range(jak1_id + Specials.special_offset, jak1_id + Caches.orb_cache_offset):
classification = ItemClassification.progression
classification = ItemClass.progression | ItemClass.useful
count = 1
# Make only 1 of each Move Item.
elif item in range(jak1_id + Caches.orb_cache_offset, jak1_id + Orbs.orb_offset):
classification = ItemClassification.progression
classification = ItemClass.progression | ItemClass.useful
count = 1
# Make N Precursor Orb bundles, where N is 2000 / bundle size.
elif item in range(jak1_id + Orbs.orb_offset, jak1_max):
classification = ItemClassification.progression_skip_balancing
if self.total_trade_orbs == 0:
classification = ItemClass.filler # If you don't need orbs to do trades, they are useless.
else:
classification = ItemClass.progression_skip_balancing
count = 2000 // self.orb_bundle_size if self.orb_bundle_size > 0 else 0 # Don't divide by zero!
# Under normal circumstances, we will create 0 filler items.
# We will manually create filler items as needed.
elif item == jak1_max:
classification = ItemClassification.filler
classification = ItemClass.filler
count = 0
# If we try to make items with ID's higher than we've defined, something has gone wrong.
@@ -193,7 +211,7 @@ class JakAndDaxterWorld(World):
# then fill the item pool with a corresponding amount of filler items.
if item_name in self.item_name_groups["Moves"] and not self.options.enable_move_randomizer:
self.multiworld.push_precollected(self.create_item(item_name))
self.multiworld.itempool += [self.create_filler()]
self.multiworld.itempool.append(self.create_filler())
continue
# Handle Orbsanity option.

View File

@@ -10,15 +10,13 @@ def build_regions(level_name: str, world: JakAndDaxterWorld) -> List[JakAndDaxte
options = world.options
player = world.player
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: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([32], access_rule=lambda state: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([33], access_rule=lambda state: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([34], access_rule=lambda state: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([35], access_rule=lambda state: world.can_trade(state, total_trade_orbs, 34))
main_area.add_cell_locations([31], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([32], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([33], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([34], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([35], access_rule=lambda state: world.can_trade(state, world.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])

View File

@@ -10,14 +10,12 @@ def build_regions(level_name: str, world: JakAndDaxterWorld) -> List[JakAndDaxte
options = world.options
player = world.player
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: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([12], access_rule=lambda state: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([11], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([12], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
# 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])
@@ -35,8 +33,8 @@ def build_regions(level_name: str, world: JakAndDaxterWorld) -> List[JakAndDaxte
yakow_cliff.add_fly_locations([75], access_rule=lambda state: can_free_scout_flies(state, player))
oracle_platforms = JakAndDaxterRegion("Oracle Platforms", player, multiworld, level_name, 6)
oracle_platforms.add_cell_locations([13], access_rule=lambda state: world.can_trade(state, total_trade_orbs, None))
oracle_platforms.add_cell_locations([14], access_rule=lambda state: world.can_trade(state, total_trade_orbs, 13))
oracle_platforms.add_cell_locations([13], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
oracle_platforms.add_cell_locations([14], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, 13))
oracle_platforms.add_fly_locations([393291], access_rule=lambda state:
can_free_scout_flies(state, player))

View File

@@ -11,16 +11,14 @@ def build_regions(level_name: str, world: JakAndDaxterWorld) -> List[JakAndDaxte
options = world.options
player = world.player
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: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([97], access_rule=lambda state: world.can_trade(state, total_trade_orbs, 96))
main_area.add_cell_locations([98], access_rule=lambda state: world.can_trade(state, total_trade_orbs, 97))
main_area.add_cell_locations([99], access_rule=lambda state: world.can_trade(state, total_trade_orbs, 98))
main_area.add_cell_locations([100], access_rule=lambda state: world.can_trade(state, total_trade_orbs, None))
main_area.add_cell_locations([101], access_rule=lambda state: world.can_trade(state, total_trade_orbs, 100))
main_area.add_cell_locations([96], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([97], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, 96))
main_area.add_cell_locations([98], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, 97))
main_area.add_cell_locations([99], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, 98))
main_area.add_cell_locations([100], access_rule=lambda state: world.can_trade(state, world.total_trade_orbs, None))
main_area.add_cell_locations([101], access_rule=lambda state: world.can_trade(state, world.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).