Skip to content

Commit

Permalink
Minor updates and optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
hesto2 committed Nov 26, 2024
1 parent 2e21484 commit f4c68d6
Show file tree
Hide file tree
Showing 17 changed files with 967 additions and 7,288 deletions.
1 change: 1 addition & 0 deletions worlds/metroidprime/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/test_output
2 changes: 1 addition & 1 deletion worlds/metroidprime/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def color_options_to_value(world: "MetroidPrimeWorld") -> List[float]:
def make_artifact_hints(world: "MetroidPrimeWorld") -> Dict[str, str]:
def make_artifact_hint(item: str) -> str:
try:
if world.options.artifact_hints.value:
if world.options.artifact_hints:
location = world.multiworld.find_item(item, world.player)
player_string = (
f"{world.multiworld.player_name[location.player]}'s"
Expand Down
42 changes: 20 additions & 22 deletions worlds/metroidprime/ItemPool.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import TYPE_CHECKING, List
from BaseClasses import ItemClassification
from .PrimeOptions import BlastShieldAvailableTypes, BlastShieldRandomization
from .Items import (
PROGRESSIVE_ITEM_MAPPING,
MetroidPrimeItem,
Expand All @@ -26,7 +27,7 @@ def generate_start_inventory(world: "MetroidPrimeWorld") -> List[str]:
for item in world.starting_room_data.selected_loadout.loadout
)

if not world.options.shuffle_scan_visor.value:
if not world.options.shuffle_scan_visor:
starting_items.append(SuitUpgrade.Scan_Visor.value)

return starting_items
Expand Down Expand Up @@ -54,7 +55,9 @@ def generate_item_pool(world: "MetroidPrimeWorld") -> List[MetroidPrimeItem]:
progressive_missiles = 8
for _ in range(progressive_missiles):
items.append(
world.create_item(SuitUpgrade.Missile_Expansion.value, ItemClassification.progression)
world.create_item(
SuitUpgrade.Missile_Expansion.value, ItemClassification.progression
)
)
items.append(
world.create_item(
Expand Down Expand Up @@ -94,7 +97,7 @@ def generate_item_pool(world: "MetroidPrimeWorld") -> List[MetroidPrimeItem]:
)

# Add beams and combos
if world.options.progressive_beam_upgrades.value:
if world.options.progressive_beam_upgrades:
for progressive_item in PROGRESSIVE_ITEM_MAPPING:
for index in range(3):
items.append(
Expand All @@ -106,28 +109,23 @@ def generate_item_pool(world: "MetroidPrimeWorld") -> List[MetroidPrimeItem]:
)
)
else:
items.append(world.create_item(SuitUpgrade.Power_Beam.value))
items.append(world.create_item(SuitUpgrade.Wave_Beam.value))
items.append(world.create_item(SuitUpgrade.Ice_Beam.value))
items.append(world.create_item(SuitUpgrade.Plasma_Beam.value))

items.append(world.create_item(SuitUpgrade.Charge_Beam.value))

items.append(world.create_item(SuitUpgrade.Super_Missile.value))

combo_classification = (
ItemClassification.progression
if requires_beam_combos_for_progression(world)
else ItemClassification.useful
)
items.append(
world.create_item(SuitUpgrade.Wavebuster.value, combo_classification)
)
items.append(
world.create_item(SuitUpgrade.Ice_Spreader.value, combo_classification)
)
items.append(
world.create_item(SuitUpgrade.Flamethrower.value, combo_classification)
items.extend(
(
world.create_item(SuitUpgrade.Power_Beam.value),
world.create_item(SuitUpgrade.Wave_Beam.value),
world.create_item(SuitUpgrade.Ice_Beam.value),
world.create_item(SuitUpgrade.Plasma_Beam.value),
world.create_item(SuitUpgrade.Charge_Beam.value),
world.create_item(SuitUpgrade.Super_Missile.value),
world.create_item(SuitUpgrade.Wavebuster.value, combo_classification),
world.create_item(SuitUpgrade.Ice_Spreader.value, combo_classification),
world.create_item(SuitUpgrade.Flamethrower.value, combo_classification),
)
)

assert world.starting_room_data.selected_loadout
Expand Down Expand Up @@ -158,9 +156,9 @@ def generate_item_pool(world: "MetroidPrimeWorld") -> List[MetroidPrimeItem]:
def requires_beam_combos_for_progression(world: "MetroidPrimeWorld") -> bool:
return (
world.options.blast_shield_available_types.value
== world.options.blast_shield_available_types.option_all
== BlastShieldAvailableTypes.option_all
and world.options.blast_shield_randomization.value
!= world.options.blast_shield_randomization.option_none # type: ignore
!= BlastShieldRandomization.option_none # type: ignore
)


Expand Down
6 changes: 3 additions & 3 deletions worlds/metroidprime/Items.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ def get_progressive_upgrade_for_item(item: SuitUpgrade) -> Optional[ProgressiveU


def __get_missile_item(world: "MetroidPrimeWorld") -> SuitUpgrade:
if world.options.missile_launcher.value:
if world.options.missile_launcher:
return SuitUpgrade.Missile_Launcher
return SuitUpgrade.Missile_Expansion


def __get_power_bomb_item(world: "MetroidPrimeWorld") -> SuitUpgrade:
if world.options.main_power_bomb.value:
if world.options.main_power_bomb:
return SuitUpgrade.Main_Power_Bomb
return SuitUpgrade.Power_Bomb_Expansion

Expand All @@ -156,7 +156,7 @@ def get_item_for_options(
return __get_missile_item(world)
if item == SuitUpgrade.Main_Power_Bomb:
return __get_power_bomb_item(world)
if world.options.progressive_beam_upgrades.value:
if world.options.progressive_beam_upgrades:
progressive_upgrade = get_progressive_upgrade_for_item(item)
if progressive_upgrade is not None:
return progressive_upgrade
Expand Down
9 changes: 4 additions & 5 deletions worlds/metroidprime/Logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def can_power_beam(world: "MetroidPrimeWorld", state: CollectionState) -> bool:


def can_power_bomb(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
if world.options.main_power_bomb.value:
if world.options.main_power_bomb:
return state.has_all(
[SuitUpgrade.Morph_Ball.value, SuitUpgrade.Main_Power_Bomb.value],
world.player,
Expand All @@ -55,7 +55,7 @@ def can_spider(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
def can_missile(
world: "MetroidPrimeWorld", state: CollectionState, num_expansions: int = 1
) -> bool:
if world.options.missile_launcher.value:
if world.options.missile_launcher:
can_shoot = state.has(SuitUpgrade.Missile_Launcher.value, world.player)
return can_shoot and (
num_expansions <= 1
Expand Down Expand Up @@ -106,8 +106,7 @@ def can_plasma_beam(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
)


def can_melt_ice(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
return can_plasma_beam(world, state)
can_melt_ice = can_plasma_beam


def can_grapple(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
Expand Down Expand Up @@ -218,7 +217,7 @@ def can_scan(world: "MetroidPrimeWorld", state: CollectionState) -> bool:


def can_heat(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
if world.options.non_varia_heat_damage.value:
if world.options.non_varia_heat_damage:
return state.has(SuitUpgrade.Varia_Suit.value, world.player)
else:
return state.has_any(
Expand Down
8 changes: 4 additions & 4 deletions worlds/metroidprime/LogicCombat.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ def _can_combat_generic(
minimal_tanks: int,
requires_charge_beam: bool = True,
) -> bool:
difficulty = world.options.combat_logic_difficulty.value
if difficulty == CombatLogicDifficulty.NO_LOGIC.value:
difficulty = CombatLogicDifficulty(world.options.combat_logic_difficulty)
if difficulty == CombatLogicDifficulty.NO_LOGIC:
return True
elif difficulty == CombatLogicDifficulty.NORMAL.value:
elif difficulty == CombatLogicDifficulty.NORMAL:
return has_energy_tanks(world, state, normal_tanks) and (
can_charge_beam(world, state) or not requires_charge_beam
)
elif difficulty == CombatLogicDifficulty.MINIMAL.value:
elif difficulty == CombatLogicDifficulty.MINIMAL:
return has_energy_tanks(world, state, minimal_tanks) and (
can_charge_beam(world, state) or not requires_charge_beam
)
Expand Down
9 changes: 4 additions & 5 deletions worlds/metroidprime/PrimeOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ class RemoveHiveMecha(Toggle):


class FusionSuit(Toggle):
"""Whether to use the fusion suit or not"""
"""If enabled, will replace all the suits in game with the Fusion Suit variants (cosmetic only). Suit color randomization will have no effect if this is enabled"""

display_name = "Fusion Suit"
default = False


class TrickDifficulty(Choice):
"""Determines which tricks, if any, are required to complete the seed. This will affect the logic of the game."""
"""Determines which tricks, if any, are required to complete the seed. This will affect the logic of the game"""

display_name = "Trick Difficulty"
option_no_tricks = -1
Expand All @@ -137,15 +137,14 @@ class TrickDifficulty(Choice):


class TrickAllowList(OptionList):
"""A list of tricks to explicitly allow in logic, regardless of selected difficulty. Values should match the trick name found here: https://github.com/Electro1512/MetroidAPrime/blob/main/data/Tricks.py#L55
For example, "Crashed Frigate Scan Dash" or "Alcove Escape" """
"""A list of trick names to explicitly allow in logic, regardless of selected difficulty. For example, "Crashed Frigate Scan Dash" or "Alcove Escape" """

display_name = "Trick Allow List"
default = []


class TrickDenyList(OptionList):
"""A list of tricks to explicitly deny in logic, regardless of selected difficulty. Values should match the trick name found here: https://github.com/Electro1512/MetroidAPrime/blob/main/data/Tricks.py#L55. For example, "Crashed Frigate Scan Dash" or "Alcove Escape" """
"""A list of trick names to explicitly deny in logic, regardless of selected difficulty. For example, "Crashed Frigate Scan Dash" or "Alcove Escape" """

display_name = "Trick Deny List"
default = []
Expand Down
2 changes: 1 addition & 1 deletion worlds/metroidprime/Regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def create_regions(world: "MetroidPrimeWorld", final_boss_selection: int):
menu.connect(starting_room, "Starting Room")

def can_access_elevator(world: "MetroidPrimeWorld", state: CollectionState) -> bool:
if world.options.pre_scan_elevators.value:
if world.options.pre_scan_elevators:
return True
return can_scan(world, state)

Expand Down
4 changes: 2 additions & 2 deletions worlds/metroidprime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def generate_early(self) -> None:
# Randomize Elevators
if self.options.elevator_mapping:
self.elevator_mapping = self.options.elevator_mapping.value
elif self.options.elevator_randomization.value:
elif self.options.elevator_randomization:
self.elevator_mapping = get_random_elevator_mapping(self)
self.options.elevator_mapping.value = self.elevator_mapping

Expand Down Expand Up @@ -263,7 +263,7 @@ def set_rules(self) -> None:
)

def post_fill(self) -> None:
if self.options.artifact_hints.value:
if self.options.artifact_hints:
start_hints: typing.Set[str] = self.options.start_hints.value
for i in artifact_table:
start_hints.add(i)
Expand Down
28 changes: 15 additions & 13 deletions worlds/metroidprime/data/BlastShieldRegions.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ def __get_chozo_region():
BlastShieldRegion(
name=RoomName.Arboretum,
doors={
RoomName.Arboretum: RoomName.Sunchamber_Lobby,
RoomName.Arboretum: RoomName.Gathering_Hall_Access,
RoomName.Sunchamber_Lobby: RoomName.Arboretum,
RoomName.Gathering_Hall_Access: RoomName.Arboretum,
},
invalid_start_rooms=[
RoomName.Arboretum,
Expand Down Expand Up @@ -200,9 +200,9 @@ def __get_chozo_region():
BlastShieldRegion(
name=RoomName.Reflecting_Pool,
doors={
RoomName.Reflecting_Pool: RoomName.Antechamber,
RoomName.Reflecting_Pool: RoomName.Save_Station_3,
RoomName.Reflecting_Pool: RoomName.Transport_Access_South,
RoomName.Antechamber: RoomName.Reflecting_Pool,
RoomName.Save_Station_3: RoomName.Reflecting_Pool,
RoomName.Transport_Access_South: RoomName.Reflecting_Pool,
},
),
],
Expand Down Expand Up @@ -307,8 +307,8 @@ def __get_phendrana_region():
name=RoomName.Ice_Ruins_East,
can_be_locked=True,
doors={
RoomName.Phendrana_Shorelines: RoomName.Ice_Ruins_Access,
RoomName.Phendrana_Shorelines: RoomName.Plaza_Walkway,
RoomName.Ice_Ruins_Access: RoomName.Phendrana_Shorelines,
RoomName.Plaza_Walkway: RoomName.Phendrana_Shorelines,
},
invalid_start_rooms=[
RoomName.Save_Station_B,
Expand Down Expand Up @@ -536,8 +536,8 @@ def __get_phazon_region():
can_be_locked=True,
doors={
RoomName.Central_Dynamo: RoomName.Quarantine_Access_A,
RoomName.Metroid_Quarantine_A: RoomName.Quarantine_Access_A,
RoomName.Metroid_Quarantine_A: RoomName.Elevator_Access_B,
RoomName.Quarantine_Access_A: RoomName.Metroid_Quarantine_A,
RoomName.Elevator_Access_B: RoomName.Metroid_Quarantine_A,
},
),
BlastShieldRegion(
Expand Down Expand Up @@ -578,6 +578,7 @@ def get_valid_blast_shield_regions_by_area(
region = __get_magmoor_region()
elif area == MetroidPrimeArea.Phazon_Mines:
region = __get_phazon_region()

if not world.starting_room_data:
return region.regions
elif world.starting_room_data.area != area or (
Expand All @@ -587,8 +588,9 @@ def get_valid_blast_shield_regions_by_area(
return region.regions

return [
region
for region in region.regions
if region.invalid_start_rooms is None
or RoomName(world.starting_room_data.name) not in region.invalid_start_rooms
blast_shield_region
for blast_shield_region in region.regions
if blast_shield_region.invalid_start_rooms is None
or RoomName(world.starting_room_data.name)
not in blast_shield_region.invalid_start_rooms
]
5 changes: 2 additions & 3 deletions worlds/metroidprime/data/Tricks.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,9 @@ class Tricks:
)
watery_hall_no_gravity_no_space_jump: TrickInfo = TrickInfo(
"Watery Hall No Gravity No Space Jump",
"Reach the Watery Hall Underwater Item without Gravity Suit or Space Jump by using a slope jump",
"Reach the Watery Hall Underwater Item without Gravity Suit or Space Jump by using a slope jump or bomb jump",
TrickDifficulty.Medium,
lambda world, state: can_move_underwater(world, state) == False
or can_bomb(world, state),
lambda world, state: True,
)

furnace_no_spider_ball = TrickInfo(
Expand Down
11 changes: 6 additions & 5 deletions worlds/metroidprime/docs/en_Metroid Prime.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

An Archipelago implementation of Metroid Prime multiworld randomizer using [randomprime](https://github.com/randovania/randomprime/)

## Setup Guide

To get started or for troubleshooting, see [the Setup Guide](./docs/setup_en.md).

## What does randomization do to this game?

In Metroid Prime, all suit upgrades and expansion items are shuffled into the multiworld, adding variety to the routes available for completing the game's objectives.
Expand All @@ -18,7 +14,7 @@ The end goal of the randomizer game can consist of:
- Defeating Ridley (configurable)
- Defeating Metroid Prime (configurable)

If randomized, the end goal can be scanned in the Temple Security station.
The end goal can be scanned in the Temple Security station.

## Which items can be in another player's world?

Expand All @@ -31,6 +27,7 @@ Multiworld items appear as one of the following:
- Progression Item: Cog
- Useful Item: Metroid Model with a random texture
- Filler Item: Zoomer Model with a random texture
- Trap Item: Cog

## What versions of the Metroid Prime are supported?

Expand Down Expand Up @@ -66,6 +63,10 @@ It is recommended to use a vanilla ISO with the latest release of [Dolphin](http
- Not compatible
- Practice Mod (The AP client is unable to connect to the game with this mod present.)

### Can tricks be included in logic?

You can select a general difficulty of tricks you want to be allowed as well as explicitly include or exclude certain tricks via the options as well. For a comprehensive list of tricks and their associated difficulties, take a look at [this document](https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/metroidprime/data/Tricks.py)

### Aside from item locations being shuffled, how does this differ from the vanilla game?

Some of the changes include:
Expand Down
2 changes: 1 addition & 1 deletion worlds/metroidprime/test/TestOutputGeneration.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class TestAllRandomizedOutput(MetroidPrimeTestBase):
auto_construct = False
options = {
"elevator_randomization": True,
"door_randomization": "regional",
"door_color_randomization": "regional",
"blast_shield_randomization": "mix_it_up",
}

Expand Down
Loading

0 comments on commit f4c68d6

Please sign in to comment.