Skip to content

Ror2: Add progressive stages option #2813

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
27 changes: 21 additions & 6 deletions worlds/ror2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class RiskOfRainWorld(World):
}
location_name_to_id = item_pickups

data_version = 8
required_client_version = (0, 4, 4)
data_version = 9
required_client_version = (0, 4, 5)
web = RiskOfWeb()
total_revivals: int

Expand Down Expand Up @@ -91,6 +91,17 @@ def create_items(self) -> None:
# only mess with the environments if they are set as items
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
environment_available_orderedstages_table = environment_vanilla_orderedstages_table
if self.options.dlc_sotv:
Expand Down Expand Up @@ -121,8 +132,12 @@ def create_items(self) -> None:
total_locations = self.options.total_locations.value
else:
# 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(
get_locations(
chests=self.options.chests_per_stage.value,
Expand Down Expand Up @@ -206,8 +221,8 @@ def fill_slot_data(self) -> Dict[str, Any]:
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",
"scanner_per_stage", "altars_per_stage", "total_revivals",
"start_with_revive", "final_stage_death", "death_link",
casing="camel")
"start_with_revive", "final_stage_death", "death_link", "require_stages",
"progressive_stages", casing="camel")
return {
**options_dict,
"seed": "".join(self.random.choice(string.digits) for _ in range(16)),
Expand Down
1 change: 0 additions & 1 deletion worlds/ror2/docs/en_Risk of Rain 2.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ settings 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
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?

Expand Down
2 changes: 1 addition & 1 deletion worlds/ror2/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class RiskOfRainItemData(NamedTuple):
"Stage 2": RiskOfRainItemData("Stage", 2 + stage_offset, ItemClassification.progression),
"Stage 3": RiskOfRainItemData("Stage", 3 + 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}
Expand Down
13 changes: 13 additions & 0 deletions worlds/ror2/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@ class DLC_SOTV(Toggle):
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):
"""Weight of Green Scraps in the item pool.

Expand Down Expand Up @@ -378,6 +389,8 @@ class ROR2Options(PerGameCommonOptions):
start_with_revive: StartWithRevive
final_stage_death: FinalStageDeath
dlc_sotv: DLC_SOTV
require_stages: RequireStages
progressive_stages: ProgressiveStages
death_link: DeathLink
item_pickup_step: ItemPickupStep
shrine_use_step: ShrineUseStep
Expand Down
23 changes: 10 additions & 13 deletions worlds/ror2/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ def has_entrance_access_rule(multiworld: MultiWorld, stage: str, region: str, pl
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:
rule = lambda state: state.has_all(items, player) and state.has(region, player)
for entrance in multiworld.get_region(region, player).entrances:
Expand Down Expand Up @@ -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)


# 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:
player = ror2_world.player
multiworld = ror2_world.multiworld
Expand Down Expand Up @@ -124,8 +122,7 @@ def set_rules(ror2_world: "RiskOfRainWorld") -> None:
for newt in range(1, newts + 1):
has_location_access_rule(multiworld, environment_name, player, newt, "Newt Altar")
if i > 0:
has_entrance_access_rule(multiworld, f"Stage {i}", environment_name, player)
get_stage_event(multiworld, player, i)
has_stage_access_rule(multiworld, f"Stage {i}", i, environment_name, player)

if ror2_options.dlc_sotv:
for i in range(len(environment_sotv_orderedstages_table)):
Expand All @@ -143,10 +140,10 @@ def set_rules(ror2_world: "RiskOfRainWorld") -> None:
for newt in range(1, newts + 1):
has_location_access_rule(multiworld, environment_name, player, newt, "Newt Altar")
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",
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, "Stage 5", "Commencement", player)
has_entrance_access_rule(multiworld, "Stage 5", "Hidden Realm: A Moment, Fractured", player)
Expand Down
4 changes: 3 additions & 1 deletion worlds/ror2/test/test_mithrix_goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

class MithrixGoalTest(RoR2TestBase):
options = {
"victory": "mithrix"
"victory": "mithrix",
"require_stages": "true",
"progressive_stages": "false"
}

def test_mithrix(self) -> None:
Expand Down