mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Pokemon Emerald: v2 Update (#2918)
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""
|
||||
Functions related to AP regions for Pokemon Emerald (see ./data/regions for region definitions)
|
||||
"""
|
||||
from typing import TYPE_CHECKING, Dict, List, Tuple
|
||||
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
from BaseClasses import ItemClassification, Region
|
||||
from BaseClasses import CollectionState, ItemClassification, Region
|
||||
|
||||
from .data import data
|
||||
from .items import PokemonEmeraldItem
|
||||
@@ -18,9 +18,80 @@ def create_regions(world: "PokemonEmeraldWorld") -> Dict[str, Region]:
|
||||
Iterates through regions created from JSON to create regions and adds them to the multiworld.
|
||||
Also creates and places events and connects regions via warps and the exits defined in the JSON.
|
||||
"""
|
||||
# Used in connect_to_map_encounters. Splits encounter categories into "subcategories" and gives them names
|
||||
# and rules so the rods can only access their specific slots.
|
||||
encounter_categories: Dict[str, List[Tuple[Optional[str], range, Optional[Callable[[CollectionState], bool]]]]] = {
|
||||
"LAND": [(None, range(0, 12), None)],
|
||||
"WATER": [(None, range(0, 5), None)],
|
||||
"FISHING": [
|
||||
("OLD_ROD", range(0, 2), lambda state: state.has("Old Rod", world.player)),
|
||||
("GOOD_ROD", range(2, 5), lambda state: state.has("Good Rod", world.player)),
|
||||
("SUPER_ROD", range(5, 10), lambda state: state.has("Super Rod", world.player)),
|
||||
],
|
||||
}
|
||||
|
||||
def connect_to_map_encounters(region: Region, map_name: str, include_slots: Tuple[bool, bool, bool]):
|
||||
"""
|
||||
Connects the provided region to the corresponding wild encounters for the given parent map.
|
||||
|
||||
Each in-game map may have a non-physical Region for encountering wild pokemon in each of the three categories
|
||||
land, water, and fishing. Region data defines whether a given region includes places where those encounters can
|
||||
be accessed (i.e. whether the region has tall grass, a river bank, is on water, etc.).
|
||||
|
||||
These regions are created lazily and dynamically so as not to bother with unused maps.
|
||||
"""
|
||||
# For each of land, water, and fishing, connect the region if indicated by include_slots
|
||||
for i, encounter_category in enumerate(encounter_categories.items()):
|
||||
if include_slots[i]:
|
||||
region_name = f"{map_name}_{encounter_category[0]}_ENCOUNTERS"
|
||||
|
||||
# If the region hasn't been created yet, create it now
|
||||
try:
|
||||
encounter_region = world.multiworld.get_region(region_name, world.player)
|
||||
except KeyError:
|
||||
encounter_region = Region(region_name, world.player, world.multiworld)
|
||||
encounter_slots = getattr(data.maps[map_name], f"{encounter_category[0].lower()}_encounters").slots
|
||||
|
||||
# Subcategory is for splitting fishing rods; land and water only have one subcategory
|
||||
for subcategory in encounter_category[1]:
|
||||
# Want to create locations per species, not per slot
|
||||
# encounter_categories includes info on which slots belong to which subcategory
|
||||
unique_species = []
|
||||
for j, species_id in enumerate(encounter_slots):
|
||||
if j in subcategory[1] and not species_id in unique_species:
|
||||
unique_species.append(species_id)
|
||||
|
||||
# Create a location for the species
|
||||
for j, species_id in enumerate(unique_species):
|
||||
encounter_location = PokemonEmeraldLocation(
|
||||
world.player,
|
||||
f"{region_name}{'_' + subcategory[0] if subcategory[0] is not None else ''}_{j + 1}",
|
||||
None,
|
||||
encounter_region
|
||||
)
|
||||
encounter_location.show_in_spoiler = False
|
||||
|
||||
# Add access rule
|
||||
if subcategory[2] is not None:
|
||||
encounter_location.access_rule = subcategory[2]
|
||||
|
||||
# Fill the location with an event for catching that species
|
||||
encounter_location.place_locked_item(PokemonEmeraldItem(
|
||||
f"CATCH_{data.species[species_id].name}",
|
||||
ItemClassification.progression_skip_balancing,
|
||||
None,
|
||||
world.player
|
||||
))
|
||||
encounter_region.locations.append(encounter_location)
|
||||
|
||||
# Add the new encounter region to the multiworld
|
||||
world.multiworld.regions.append(encounter_region)
|
||||
|
||||
# Encounter region exists, just connect to it
|
||||
region.connect(encounter_region, f"{region.name} -> {region_name}")
|
||||
|
||||
regions: Dict[str, Region] = {}
|
||||
connections: List[Tuple[str, str, str]] = []
|
||||
|
||||
for region_name, region_data in data.regions.items():
|
||||
new_region = Region(region_name, world.player, world.multiworld)
|
||||
|
||||
@@ -40,6 +111,9 @@ def create_regions(world: "PokemonEmeraldWorld") -> Dict[str, Region]:
|
||||
|
||||
regions[region_name] = new_region
|
||||
|
||||
connect_to_map_encounters(new_region, region_data.parent_map.name,
|
||||
(region_data.has_grass, region_data.has_water, region_data.has_fishing))
|
||||
|
||||
for name, source, dest in connections:
|
||||
regions[source].connect(regions[dest], name)
|
||||
|
||||
|
Reference in New Issue
Block a user