Ror2: Add progressive stages option (#2813)

This commit is contained in:
Rjosephson 2024-04-09 13:14:18 -06:00 committed by GitHub
parent 32c92e03e7
commit b007a42487
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 48 additions and 22 deletions

View File

@ -44,8 +44,8 @@ class RiskOfRainWorld(World):
} }
location_name_to_id = item_pickups location_name_to_id = item_pickups
data_version = 8 data_version = 9
required_client_version = (0, 4, 4) required_client_version = (0, 4, 5)
web = RiskOfWeb() web = RiskOfWeb()
total_revivals: int total_revivals: int
@ -91,6 +91,17 @@ class RiskOfRainWorld(World):
# only mess with the environments if they are set as items # only mess with the environments if they are set as items
if self.options.goal == "explore": if self.options.goal == "explore":
# check to see if the user doesn't want to use stages, and to figure out what type of stages are being used.
if not self.options.require_stages:
if not self.options.progressive_stages:
self.multiworld.push_precollected(self.multiworld.create_item("Stage 1", self.player))
self.multiworld.push_precollected(self.multiworld.create_item("Stage 2", self.player))
self.multiworld.push_precollected(self.multiworld.create_item("Stage 3", self.player))
self.multiworld.push_precollected(self.multiworld.create_item("Stage 4", self.player))
else:
for _ in range(4):
self.multiworld.push_precollected(self.multiworld.create_item("Progressive Stage", self.player))
# figure out all available ordered stages for each tier # figure out all available ordered stages for each tier
environment_available_orderedstages_table = environment_vanilla_orderedstages_table environment_available_orderedstages_table = environment_vanilla_orderedstages_table
if self.options.dlc_sotv: if self.options.dlc_sotv:
@ -121,8 +132,12 @@ class RiskOfRainWorld(World):
total_locations = self.options.total_locations.value total_locations = self.options.total_locations.value
else: else:
# explore mode # explore mode
# Add Stage items for logic gates
itempool += ["Stage 1", "Stage 2", "Stage 3", "Stage 4"] # Add Stage items to the pool
if self.options.require_stages:
itempool += ["Stage 1", "Stage 2", "Stage 3", "Stage 4"] if not self.options.progressive_stages else \
["Progressive Stage"] * 4
total_locations = len( total_locations = len(
get_locations( get_locations(
chests=self.options.chests_per_stage.value, chests=self.options.chests_per_stage.value,
@ -206,8 +221,8 @@ class RiskOfRainWorld(World):
options_dict = self.options.as_dict("item_pickup_step", "shrine_use_step", "goal", "victory", "total_locations", options_dict = self.options.as_dict("item_pickup_step", "shrine_use_step", "goal", "victory", "total_locations",
"chests_per_stage", "shrines_per_stage", "scavengers_per_stage", "chests_per_stage", "shrines_per_stage", "scavengers_per_stage",
"scanner_per_stage", "altars_per_stage", "total_revivals", "scanner_per_stage", "altars_per_stage", "total_revivals",
"start_with_revive", "final_stage_death", "death_link", "start_with_revive", "final_stage_death", "death_link", "require_stages",
casing="camel") "progressive_stages", casing="camel")
return { return {
**options_dict, **options_dict,
"seed": "".join(self.random.choice(string.digits) for _ in range(16)), "seed": "".join(self.random.choice(string.digits) for _ in range(16)),

View File

@ -57,7 +57,6 @@ options apply, so each Risk of Rain 2 player slot in the multiworld needs to be
for example, have two players trade off hosting and making progress on each other's player slot, but a single co-op for example, have two players trade off hosting and making progress on each other's player slot, but a single co-op
instance can't make progress towards multiple player slots in the multiworld. instance can't make progress towards multiple player slots in the multiworld.
Explore mode is untested in multiplayer and will likely not work until a later release.
## What Risk of Rain items can appear in other players' worlds? ## What Risk of Rain items can appear in other players' worlds?

View File

@ -59,7 +59,7 @@ stage_table: Dict[str, RiskOfRainItemData] = {
"Stage 2": RiskOfRainItemData("Stage", 2 + stage_offset, ItemClassification.progression), "Stage 2": RiskOfRainItemData("Stage", 2 + stage_offset, ItemClassification.progression),
"Stage 3": RiskOfRainItemData("Stage", 3 + stage_offset, ItemClassification.progression), "Stage 3": RiskOfRainItemData("Stage", 3 + stage_offset, ItemClassification.progression),
"Stage 4": RiskOfRainItemData("Stage", 4 + stage_offset, ItemClassification.progression), "Stage 4": RiskOfRainItemData("Stage", 4 + stage_offset, ItemClassification.progression),
"Progressive Stage": RiskOfRainItemData("Stage", 5 + stage_offset, ItemClassification.progression),
} }
item_table = {**upgrade_table, **other_table, **filler_table, **trap_table, **stage_table} item_table = {**upgrade_table, **other_table, **filler_table, **trap_table, **stage_table}

View File

@ -151,6 +151,17 @@ class DLC_SOTV(Toggle):
display_name = "Enable DLC - SOTV" display_name = "Enable DLC - SOTV"
class RequireStages(DefaultOnToggle):
"""Add Stage items to the pool to block access to the next set of environments."""
display_name = "Require Stages"
class ProgressiveStages(DefaultOnToggle):
"""This will convert Stage items to be a progressive item. For example instead of "Stage 2" it would be
"Progressive Stage" """
display_name = "Progressive Stages"
class GreenScrap(Range): class GreenScrap(Range):
"""Weight of Green Scraps in the item pool. """Weight of Green Scraps in the item pool.
@ -378,6 +389,8 @@ class ROR2Options(PerGameCommonOptions):
start_with_revive: StartWithRevive start_with_revive: StartWithRevive
final_stage_death: FinalStageDeath final_stage_death: FinalStageDeath
dlc_sotv: DLC_SOTV dlc_sotv: DLC_SOTV
require_stages: RequireStages
progressive_stages: ProgressiveStages
death_link: DeathLink death_link: DeathLink
item_pickup_step: ItemPickupStep item_pickup_step: ItemPickupStep
shrine_use_step: ShrineUseStep shrine_use_step: ShrineUseStep

View File

@ -15,6 +15,13 @@ def has_entrance_access_rule(multiworld: MultiWorld, stage: str, region: str, pl
entrance.access_rule = rule entrance.access_rule = rule
def has_stage_access_rule(multiworld: MultiWorld, stage: str, amount: int, region: str, player: int) -> None:
rule = lambda state: state.has(region, player) and \
(state.has(stage, player) or state.count("Progressive Stage", player) >= amount)
for entrance in multiworld.get_region(region, player).entrances:
entrance.access_rule = rule
def has_all_items(multiworld: MultiWorld, items: Set[str], region: str, player: int) -> None: def has_all_items(multiworld: MultiWorld, items: Set[str], region: str, player: int) -> None:
rule = lambda state: state.has_all(items, player) and state.has(region, player) rule = lambda state: state.has_all(items, player) and state.has(region, player)
for entrance in multiworld.get_region(region, player).entrances: for entrance in multiworld.get_region(region, player).entrances:
@ -43,15 +50,6 @@ def check_location(state, environment: str, player: int, item_number: int, item_
return state.can_reach(f"{environment}: {item_name} {item_number - 1}", "Location", player) return state.can_reach(f"{environment}: {item_name} {item_number - 1}", "Location", player)
# unlock event to next set of stages
def get_stage_event(multiworld: MultiWorld, player: int, stage_number: int) -> None:
if stage_number == 4:
return
rule = lambda state: state.has(f"Stage {stage_number + 1}", player)
for entrance in multiworld.get_region(f"OrderedStage_{stage_number + 1}", player).entrances:
entrance.access_rule = rule
def set_rules(ror2_world: "RiskOfRainWorld") -> None: def set_rules(ror2_world: "RiskOfRainWorld") -> None:
player = ror2_world.player player = ror2_world.player
multiworld = ror2_world.multiworld multiworld = ror2_world.multiworld
@ -124,8 +122,7 @@ def set_rules(ror2_world: "RiskOfRainWorld") -> None:
for newt in range(1, newts + 1): for newt in range(1, newts + 1):
has_location_access_rule(multiworld, environment_name, player, newt, "Newt Altar") has_location_access_rule(multiworld, environment_name, player, newt, "Newt Altar")
if i > 0: if i > 0:
has_entrance_access_rule(multiworld, f"Stage {i}", environment_name, player) has_stage_access_rule(multiworld, f"Stage {i}", i, environment_name, player)
get_stage_event(multiworld, player, i)
if ror2_options.dlc_sotv: if ror2_options.dlc_sotv:
for i in range(len(environment_sotv_orderedstages_table)): for i in range(len(environment_sotv_orderedstages_table)):
@ -143,10 +140,10 @@ def set_rules(ror2_world: "RiskOfRainWorld") -> None:
for newt in range(1, newts + 1): for newt in range(1, newts + 1):
has_location_access_rule(multiworld, environment_name, player, newt, "Newt Altar") has_location_access_rule(multiworld, environment_name, player, newt, "Newt Altar")
if i > 0: if i > 0:
has_entrance_access_rule(multiworld, f"Stage {i}", environment_name, player) has_stage_access_rule(multiworld, f"Stage {i}", i, environment_name, player)
has_entrance_access_rule(multiworld, "Hidden Realm: A Moment, Fractured", "Hidden Realm: A Moment, Whole", has_entrance_access_rule(multiworld, "Hidden Realm: A Moment, Fractured", "Hidden Realm: A Moment, Whole",
player) player)
has_entrance_access_rule(multiworld, "Stage 1", "Hidden Realm: Bazaar Between Time", player) has_stage_access_rule(multiworld, "Stage 1", 1, "Hidden Realm: Bazaar Between Time", player)
has_entrance_access_rule(multiworld, "Hidden Realm: Bazaar Between Time", "Void Fields", player) has_entrance_access_rule(multiworld, "Hidden Realm: Bazaar Between Time", "Void Fields", player)
has_entrance_access_rule(multiworld, "Stage 5", "Commencement", player) has_entrance_access_rule(multiworld, "Stage 5", "Commencement", player)
has_entrance_access_rule(multiworld, "Stage 5", "Hidden Realm: A Moment, Fractured", player) has_entrance_access_rule(multiworld, "Stage 5", "Hidden Realm: A Moment, Fractured", player)

View File

@ -3,7 +3,9 @@ from . import RoR2TestBase
class MithrixGoalTest(RoR2TestBase): class MithrixGoalTest(RoR2TestBase):
options = { options = {
"victory": "mithrix" "victory": "mithrix",
"require_stages": "true",
"progressive_stages": "false"
} }
def test_mithrix(self) -> None: def test_mithrix(self) -> None: