120 lines
6.0 KiB
Python
120 lines
6.0 KiB
Python
from typing import Tuple
|
|
from BaseClasses import Location
|
|
from .Options import TotalLocations
|
|
from .Options import ChestsPerEnvironment
|
|
from .Options import ShrinesPerEnvironment
|
|
from .Options import ScavengersPerEnvironment
|
|
from .Options import ScannersPerEnvironment
|
|
from .Options import AltarsPerEnvironment
|
|
from .RoR2Environments import *
|
|
|
|
|
|
class RiskOfRainLocation(Location):
|
|
game: str = "Risk of Rain 2"
|
|
|
|
|
|
ror2_locations_start_id = 38000
|
|
|
|
|
|
def get_classic_item_pickups(n: int) -> Dict[str, int]:
|
|
"""Get n ItemPickups, capped at the max value for TotalLocations"""
|
|
n = max(n, 0)
|
|
n = min(n, TotalLocations.range_end)
|
|
return { f"ItemPickup{i+1}": ror2_locations_start_id+i for i in range(n) }
|
|
|
|
|
|
item_pickups = get_classic_item_pickups(TotalLocations.range_end)
|
|
location_table = item_pickups
|
|
|
|
|
|
def environment_abreviation(long_name:str) -> str:
|
|
"""convert long environment names to initials"""
|
|
abrev = ""
|
|
# go through every word finding a letter (or number) for an initial
|
|
for word in long_name.split():
|
|
initial = word[0]
|
|
for letter in word:
|
|
if letter.isalnum():
|
|
initial = letter
|
|
break
|
|
abrev+= initial
|
|
return abrev
|
|
|
|
# highest numbered orderedstages (this is so we can treat the easily caculate the check ids based on the environment and location "offset")
|
|
highest_orderedstage: int= max(compress_dict_list_horizontal(environment_orderedstages_table).values())
|
|
|
|
ror2_locations_start_orderedstage = ror2_locations_start_id + TotalLocations.range_end
|
|
|
|
class orderedstage_location:
|
|
"""A class to behave like a struct for storing the offsets of location types in the allocated space per orderedstage environments."""
|
|
# TODO is there a better, more generic way to do this?
|
|
offset_ChestsPerEnvironment = 0
|
|
offset_ShrinesPerEnvironment = offset_ChestsPerEnvironment + ChestsPerEnvironment.range_end
|
|
offset_ScavengersPerEnvironment = offset_ShrinesPerEnvironment + ShrinesPerEnvironment.range_end
|
|
offset_ScannersPerEnvironment = offset_ScavengersPerEnvironment + ScavengersPerEnvironment.range_end
|
|
offset_AltarsPerEnvironment = offset_ScannersPerEnvironment + ScannersPerEnvironment.range_end
|
|
|
|
# total space allocated to the locations in a single orderedstage environment
|
|
allocation = offset_AltarsPerEnvironment + AltarsPerEnvironment.range_end
|
|
|
|
def get_environment_locations(chests:int, shrines:int, scavengers:int, scanners:int, altars:int, environment: Tuple[str, int]) -> Dict[str, int]:
|
|
"""Get the locations within a specific environment"""
|
|
environment_name = environment[0]
|
|
environment_index = environment[1]
|
|
locations = {}
|
|
|
|
# due to this mapping, since environment ids are not consecutive, there are lots of "wasted" id numbers
|
|
# TODO perhaps a hashing algorithm could be used to compress this range and save "wasted" ids
|
|
environment_start_id = environment_index * orderedstage_location.allocation + ror2_locations_start_orderedstage
|
|
for n in range(chests):
|
|
locations.update({f"{environment_name}: Chest {n+1}": n + orderedstage_location.offset_ChestsPerEnvironment + environment_start_id})
|
|
for n in range(shrines):
|
|
locations.update({f"{environment_name}: Shrine {n+1}": n + orderedstage_location.offset_ShrinesPerEnvironment + environment_start_id})
|
|
for n in range(scavengers):
|
|
locations.update({f"{environment_name}: Scavenger {n+1}": n + orderedstage_location.offset_ScavengersPerEnvironment + environment_start_id})
|
|
for n in range(scanners):
|
|
locations.update({f"{environment_name}: Radio Scanner {n+1}": n + orderedstage_location.offset_ScannersPerEnvironment + environment_start_id})
|
|
for n in range(altars):
|
|
locations.update({f"{environment_name}: Newt Altar {n+1}": n + orderedstage_location.offset_AltarsPerEnvironment + environment_start_id})
|
|
return locations
|
|
|
|
def get_locations(chests:int, shrines:int, scavengers:int, scanners:int, altars:int, dlc_sotv:bool) -> Dict[str, int]:
|
|
"""Get a dictionary of locations for the ordedstage environments with the locations from the parameters."""
|
|
locations = {}
|
|
orderedstages = compress_dict_list_horizontal(environment_vanilla_orderedstages_table)
|
|
if(dlc_sotv): orderedstages.update(compress_dict_list_horizontal(environment_sotv_orderedstages_table))
|
|
# for every environment, generate the respective locations
|
|
for environment_name, environment_index in orderedstages.items():
|
|
# locations = locations | orderedstage_location.get_environment_locations(
|
|
locations.update(orderedstage_location.get_environment_locations(
|
|
chests=chests,
|
|
shrines=shrines,
|
|
scavengers=scavengers,
|
|
scanners=scanners,
|
|
altars=altars,
|
|
environment=(environment_name, environment_index)
|
|
))
|
|
return locations
|
|
|
|
def getall_locations(dlc_sotv:bool=True) -> Dict[str, int]:
|
|
"""
|
|
Get all locations in ordered stages.
|
|
Set dlc_sotv to true for the SOTV DLC to be included.
|
|
"""
|
|
# to get all locations, attempt using as many locations as possible
|
|
return orderedstage_location.get_locations(
|
|
chests=ChestsPerEnvironment.range_end,
|
|
shrines=ShrinesPerEnvironment.range_end,
|
|
scavengers=ScavengersPerEnvironment.range_end,
|
|
scanners=ScannersPerEnvironment.range_end,
|
|
altars=AltarsPerEnvironment.range_end,
|
|
dlc_sotv=dlc_sotv
|
|
)
|
|
|
|
|
|
ror2_location_post_orderedstage = ror2_locations_start_orderedstage + highest_orderedstage*orderedstage_location.allocation
|
|
location_table.update(orderedstage_location.getall_locations())
|
|
# use the sotv dlc in the lookup table so that all ids can be looked up regardless of use
|
|
|
|
lookup_id_to_name: Dict[int, str] = {id: name for name, id in location_table.items()}
|