LTTP: sort of use new options system (#3764)
* LttP: switch to dataclass options definition * LttP: write old options onto multiworld LttP: use World.random
This commit is contained in:
parent
ce210cd4ee
commit
30b414429f
|
@ -1,7 +1,7 @@
|
||||||
import typing
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from BaseClasses import MultiWorld
|
from BaseClasses import MultiWorld
|
||||||
from Options import Choice, Range, DeathLink, DefaultOnToggle, FreeText, ItemsAccessibility, Option, \
|
from Options import Choice, Range, DeathLink, DefaultOnToggle, FreeText, ItemsAccessibility, PerGameCommonOptions, \
|
||||||
PlandoBosses, PlandoConnections, PlandoTexts, Removed, StartInventoryPool, Toggle
|
PlandoBosses, PlandoConnections, PlandoTexts, Removed, StartInventoryPool, Toggle
|
||||||
from .EntranceShuffle import default_connections, default_dungeon_connections, \
|
from .EntranceShuffle import default_connections, default_dungeon_connections, \
|
||||||
inverted_default_connections, inverted_default_dungeon_connections
|
inverted_default_connections, inverted_default_dungeon_connections
|
||||||
|
@ -742,86 +742,86 @@ class ALttPPlandoTexts(PlandoTexts):
|
||||||
valid_keys = TextTable.valid_keys
|
valid_keys = TextTable.valid_keys
|
||||||
|
|
||||||
|
|
||||||
alttp_options: typing.Dict[str, type(Option)] = {
|
@dataclass
|
||||||
"accessibility": ItemsAccessibility,
|
class ALTTPOptions(PerGameCommonOptions):
|
||||||
"plando_connections": ALttPPlandoConnections,
|
accessibility: ItemsAccessibility
|
||||||
"plando_texts": ALttPPlandoTexts,
|
plando_connections: ALttPPlandoConnections
|
||||||
"start_inventory_from_pool": StartInventoryPool,
|
plando_texts: ALttPPlandoTexts
|
||||||
"goal": Goal,
|
start_inventory_from_pool: StartInventoryPool
|
||||||
"mode": Mode,
|
goal: Goal
|
||||||
"glitches_required": GlitchesRequired,
|
mode: Mode
|
||||||
"dark_room_logic": DarkRoomLogic,
|
glitches_required: GlitchesRequired
|
||||||
"open_pyramid": OpenPyramid,
|
dark_room_logic: DarkRoomLogic
|
||||||
"crystals_needed_for_gt": CrystalsTower,
|
open_pyramid: OpenPyramid
|
||||||
"crystals_needed_for_ganon": CrystalsGanon,
|
crystals_needed_for_gt: CrystalsTower
|
||||||
"triforce_pieces_mode": TriforcePiecesMode,
|
crystals_needed_for_ganon: CrystalsGanon
|
||||||
"triforce_pieces_percentage": TriforcePiecesPercentage,
|
triforce_pieces_mode: TriforcePiecesMode
|
||||||
"triforce_pieces_required": TriforcePiecesRequired,
|
triforce_pieces_percentage: TriforcePiecesPercentage
|
||||||
"triforce_pieces_available": TriforcePiecesAvailable,
|
triforce_pieces_required: TriforcePiecesRequired
|
||||||
"triforce_pieces_extra": TriforcePiecesExtra,
|
triforce_pieces_available: TriforcePiecesAvailable
|
||||||
"entrance_shuffle": EntranceShuffle,
|
triforce_pieces_extra: TriforcePiecesExtra
|
||||||
"entrance_shuffle_seed": EntranceShuffleSeed,
|
entrance_shuffle: EntranceShuffle
|
||||||
"big_key_shuffle": big_key_shuffle,
|
entrance_shuffle_seed: EntranceShuffleSeed
|
||||||
"small_key_shuffle": small_key_shuffle,
|
big_key_shuffle: big_key_shuffle
|
||||||
"key_drop_shuffle": key_drop_shuffle,
|
small_key_shuffle: small_key_shuffle
|
||||||
"compass_shuffle": compass_shuffle,
|
key_drop_shuffle: key_drop_shuffle
|
||||||
"map_shuffle": map_shuffle,
|
compass_shuffle: compass_shuffle
|
||||||
"restrict_dungeon_item_on_boss": RestrictBossItem,
|
map_shuffle: map_shuffle
|
||||||
"item_pool": ItemPool,
|
restrict_dungeon_item_on_boss: RestrictBossItem
|
||||||
"item_functionality": ItemFunctionality,
|
item_pool: ItemPool
|
||||||
"enemy_health": EnemyHealth,
|
item_functionality: ItemFunctionality
|
||||||
"enemy_damage": EnemyDamage,
|
enemy_health: EnemyHealth
|
||||||
"progressive": Progressive,
|
enemy_damage: EnemyDamage
|
||||||
"swordless": Swordless,
|
progressive: Progressive
|
||||||
"dungeon_counters": DungeonCounters,
|
swordless: Swordless
|
||||||
"retro_bow": RetroBow,
|
dungeon_counters: DungeonCounters
|
||||||
"retro_caves": RetroCaves,
|
retro_bow: RetroBow
|
||||||
"hints": Hints,
|
retro_caves: RetroCaves
|
||||||
"scams": Scams,
|
hints: Hints
|
||||||
"boss_shuffle": LTTPBosses,
|
scams: Scams
|
||||||
"pot_shuffle": PotShuffle,
|
boss_shuffle: LTTPBosses
|
||||||
"enemy_shuffle": EnemyShuffle,
|
pot_shuffle: PotShuffle
|
||||||
"killable_thieves": KillableThieves,
|
enemy_shuffle: EnemyShuffle
|
||||||
"bush_shuffle": BushShuffle,
|
killable_thieves: KillableThieves
|
||||||
"shop_item_slots": ShopItemSlots,
|
bush_shuffle: BushShuffle
|
||||||
"randomize_shop_inventories": RandomizeShopInventories,
|
shop_item_slots: ShopItemSlots
|
||||||
"shuffle_shop_inventories": ShuffleShopInventories,
|
randomize_shop_inventories: RandomizeShopInventories
|
||||||
"include_witch_hut": IncludeWitchHut,
|
shuffle_shop_inventories: ShuffleShopInventories
|
||||||
"randomize_shop_prices": RandomizeShopPrices,
|
include_witch_hut: IncludeWitchHut
|
||||||
"randomize_cost_types": RandomizeCostTypes,
|
randomize_shop_prices: RandomizeShopPrices
|
||||||
"shop_price_modifier": ShopPriceModifier,
|
randomize_cost_types: RandomizeCostTypes
|
||||||
"shuffle_capacity_upgrades": ShuffleCapacityUpgrades,
|
shop_price_modifier: ShopPriceModifier
|
||||||
"bombless_start": BomblessStart,
|
shuffle_capacity_upgrades: ShuffleCapacityUpgrades
|
||||||
"shuffle_prizes": ShufflePrizes,
|
bombless_start: BomblessStart
|
||||||
"tile_shuffle": TileShuffle,
|
shuffle_prizes: ShufflePrizes
|
||||||
"misery_mire_medallion": MiseryMireMedallion,
|
tile_shuffle: TileShuffle
|
||||||
"turtle_rock_medallion": TurtleRockMedallion,
|
misery_mire_medallion: MiseryMireMedallion
|
||||||
"glitch_boots": GlitchBoots,
|
turtle_rock_medallion: TurtleRockMedallion
|
||||||
"beemizer_total_chance": BeemizerTotalChance,
|
glitch_boots: GlitchBoots
|
||||||
"beemizer_trap_chance": BeemizerTrapChance,
|
beemizer_total_chance: BeemizerTotalChance
|
||||||
"timer": Timer,
|
beemizer_trap_chance: BeemizerTrapChance
|
||||||
"countdown_start_time": CountdownStartTime,
|
timer: Timer
|
||||||
"red_clock_time": RedClockTime,
|
countdown_start_time: CountdownStartTime
|
||||||
"blue_clock_time": BlueClockTime,
|
red_clock_time: RedClockTime
|
||||||
"green_clock_time": GreenClockTime,
|
blue_clock_time: BlueClockTime
|
||||||
"death_link": DeathLink,
|
green_clock_time: GreenClockTime
|
||||||
"allow_collect": AllowCollect,
|
death_link: DeathLink
|
||||||
"ow_palettes": OWPalette,
|
allow_collect: AllowCollect
|
||||||
"uw_palettes": UWPalette,
|
ow_palettes: OWPalette
|
||||||
"hud_palettes": HUDPalette,
|
uw_palettes: UWPalette
|
||||||
"sword_palettes": SwordPalette,
|
hud_palettes: HUDPalette
|
||||||
"shield_palettes": ShieldPalette,
|
sword_palettes: SwordPalette
|
||||||
# "link_palettes": LinkPalette,
|
shield_palettes: ShieldPalette
|
||||||
"heartbeep": HeartBeep,
|
# link_palettes: LinkPalette
|
||||||
"heartcolor": HeartColor,
|
heartbeep: HeartBeep
|
||||||
"quickswap": QuickSwap,
|
heartcolor: HeartColor
|
||||||
"menuspeed": MenuSpeed,
|
quickswap: QuickSwap
|
||||||
"music": Music,
|
menuspeed: MenuSpeed
|
||||||
"reduceflashing": ReduceFlashing,
|
music: Music
|
||||||
"triforcehud": TriforceHud,
|
reduceflashing: ReduceFlashing
|
||||||
|
triforcehud: TriforceHud
|
||||||
|
|
||||||
# removed:
|
# removed:
|
||||||
"goals": Removed,
|
goals: Removed
|
||||||
"smallkey_shuffle": Removed,
|
smallkey_shuffle: Removed
|
||||||
"bigkey_shuffle": Removed,
|
bigkey_shuffle: Removed
|
||||||
}
|
|
||||||
|
|
|
@ -782,8 +782,8 @@ def get_nonnative_item_sprite(code: int) -> int:
|
||||||
|
|
||||||
|
|
||||||
def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
|
def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
|
||||||
local_random = world.per_slot_randoms[player]
|
|
||||||
local_world = world.worlds[player]
|
local_world = world.worlds[player]
|
||||||
|
local_random = local_world.random
|
||||||
|
|
||||||
# patch items
|
# patch items
|
||||||
|
|
||||||
|
@ -1867,7 +1867,7 @@ def apply_oof_sfx(rom, oof: str):
|
||||||
def apply_rom_settings(rom, beep, color, quickswap, menuspeed, music: bool, sprite: str, oof: str, palettes_options,
|
def apply_rom_settings(rom, beep, color, quickswap, menuspeed, music: bool, sprite: str, oof: str, palettes_options,
|
||||||
world=None, player=1, allow_random_on_event=False, reduceflashing=False,
|
world=None, player=1, allow_random_on_event=False, reduceflashing=False,
|
||||||
triforcehud: str = None, deathlink: bool = False, allowcollect: bool = False):
|
triforcehud: str = None, deathlink: bool = False, allowcollect: bool = False):
|
||||||
local_random = random if not world else world.per_slot_randoms[player]
|
local_random = random if not world else world.worlds[player].random
|
||||||
disable_music: bool = not music
|
disable_music: bool = not music
|
||||||
# enable instant item menu
|
# enable instant item menu
|
||||||
if menuspeed == 'instant':
|
if menuspeed == 'instant':
|
||||||
|
@ -2197,8 +2197,9 @@ def write_string_to_rom(rom, target, string):
|
||||||
|
|
||||||
def write_strings(rom, world, player):
|
def write_strings(rom, world, player):
|
||||||
from . import ALTTPWorld
|
from . import ALTTPWorld
|
||||||
local_random = world.per_slot_randoms[player]
|
|
||||||
w: ALTTPWorld = world.worlds[player]
|
w: ALTTPWorld = world.worlds[player]
|
||||||
|
local_random = w.random
|
||||||
|
|
||||||
tt = TextTable()
|
tt = TextTable()
|
||||||
tt.removeUnwantedText()
|
tt.removeUnwantedText()
|
||||||
|
@ -2425,7 +2426,7 @@ def write_strings(rom, world, player):
|
||||||
if world.worlds[player].has_progressive_bows and (w.difficulty_requirements.progressive_bow_limit >= 2 or (
|
if world.worlds[player].has_progressive_bows and (w.difficulty_requirements.progressive_bow_limit >= 2 or (
|
||||||
world.swordless[player] or world.glitches_required[player] == 'no_glitches')):
|
world.swordless[player] or world.glitches_required[player] == 'no_glitches')):
|
||||||
prog_bow_locs = world.find_item_locations('Progressive Bow', player, True)
|
prog_bow_locs = world.find_item_locations('Progressive Bow', player, True)
|
||||||
world.per_slot_randoms[player].shuffle(prog_bow_locs)
|
local_random.shuffle(prog_bow_locs)
|
||||||
found_bow = False
|
found_bow = False
|
||||||
found_bow_alt = False
|
found_bow_alt = False
|
||||||
while prog_bow_locs and not (found_bow and found_bow_alt):
|
while prog_bow_locs and not (found_bow and found_bow_alt):
|
||||||
|
|
|
@ -1,28 +1,27 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import settings
|
|
||||||
import threading
|
import threading
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import Utils
|
import settings
|
||||||
from BaseClasses import Item, CollectionState, Tutorial, MultiWorld
|
from BaseClasses import Item, CollectionState, Tutorial, MultiWorld
|
||||||
|
from worlds.AutoWorld import World, WebWorld, LogicMixin
|
||||||
|
from .Client import ALTTPSNIClient
|
||||||
from .Dungeons import create_dungeons, Dungeon
|
from .Dungeons import create_dungeons, Dungeon
|
||||||
from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_connect
|
from .EntranceShuffle import link_entrances, link_inverted_entrances, plando_connect
|
||||||
from .InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
from .InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
||||||
from .ItemPool import generate_itempool, difficulties
|
from .ItemPool import generate_itempool, difficulties
|
||||||
from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem
|
from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem
|
||||||
from .Options import alttp_options, small_key_shuffle
|
from .Options import ALTTPOptions, small_key_shuffle
|
||||||
from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \
|
from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions, lookup_vanilla_location_to_entrance, \
|
||||||
is_main_entrance, key_drop_data
|
is_main_entrance, key_drop_data
|
||||||
from .Client import ALTTPSNIClient
|
|
||||||
from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \
|
from .Rom import LocalRom, patch_rom, patch_race_rom, check_enemizer, patch_enemizer, apply_rom_settings, \
|
||||||
get_hash_string, get_base_rom_path, LttPDeltaPatch
|
get_hash_string, get_base_rom_path, LttPDeltaPatch
|
||||||
from .Rules import set_rules
|
from .Rules import set_rules
|
||||||
from .Shops import create_shops, Shop, push_shop_inventories, ShopType, price_rate_display, price_type_display_name
|
from .Shops import create_shops, Shop, push_shop_inventories, ShopType, price_rate_display, price_type_display_name
|
||||||
from .SubClasses import ALttPItem, LTTPRegionType
|
|
||||||
from worlds.AutoWorld import World, WebWorld, LogicMixin
|
|
||||||
from .StateHelpers import can_buy_unlimited
|
from .StateHelpers import can_buy_unlimited
|
||||||
|
from .SubClasses import ALttPItem, LTTPRegionType
|
||||||
|
|
||||||
lttp_logger = logging.getLogger("A Link to the Past")
|
lttp_logger = logging.getLogger("A Link to the Past")
|
||||||
|
|
||||||
|
@ -132,7 +131,8 @@ class ALTTPWorld(World):
|
||||||
Ganon!
|
Ganon!
|
||||||
"""
|
"""
|
||||||
game = "A Link to the Past"
|
game = "A Link to the Past"
|
||||||
option_definitions = alttp_options
|
options_dataclass = ALTTPOptions
|
||||||
|
options: ALTTPOptions
|
||||||
settings_key = "lttp_options"
|
settings_key = "lttp_options"
|
||||||
settings: typing.ClassVar[ALTTPSettings]
|
settings: typing.ClassVar[ALTTPSettings]
|
||||||
topology_present = True
|
topology_present = True
|
||||||
|
@ -286,13 +286,22 @@ class ALTTPWorld(World):
|
||||||
if not os.path.exists(rom_file):
|
if not os.path.exists(rom_file):
|
||||||
raise FileNotFoundError(rom_file)
|
raise FileNotFoundError(rom_file)
|
||||||
if multiworld.is_race:
|
if multiworld.is_race:
|
||||||
import xxtea
|
import xxtea # noqa
|
||||||
for player in multiworld.get_game_players(cls.game):
|
for player in multiworld.get_game_players(cls.game):
|
||||||
if multiworld.worlds[player].use_enemizer:
|
if multiworld.worlds[player].use_enemizer:
|
||||||
check_enemizer(multiworld.worlds[player].enemizer_path)
|
check_enemizer(multiworld.worlds[player].enemizer_path)
|
||||||
break
|
break
|
||||||
|
|
||||||
def generate_early(self):
|
def generate_early(self):
|
||||||
|
# write old options
|
||||||
|
import dataclasses
|
||||||
|
is_first = self.player == min(self.multiworld.get_game_players(self.game))
|
||||||
|
|
||||||
|
for field in dataclasses.fields(self.options_dataclass):
|
||||||
|
if is_first:
|
||||||
|
setattr(self.multiworld, field.name, {})
|
||||||
|
getattr(self.multiworld, field.name)[self.player] = getattr(self.options, field.name)
|
||||||
|
# end of old options re-establisher
|
||||||
|
|
||||||
player = self.player
|
player = self.player
|
||||||
multiworld = self.multiworld
|
multiworld = self.multiworld
|
||||||
|
@ -536,12 +545,10 @@ class ALTTPWorld(World):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def use_enemizer(self) -> bool:
|
def use_enemizer(self) -> bool:
|
||||||
world = self.multiworld
|
return bool(self.options.boss_shuffle or self.options.enemy_shuffle
|
||||||
player = self.player
|
or self.options.enemy_health != 'default' or self.options.enemy_damage != 'default'
|
||||||
return bool(world.boss_shuffle[player] or world.enemy_shuffle[player]
|
or self.options.pot_shuffle or self.options.bush_shuffle
|
||||||
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
or self.options.killable_thieves)
|
||||||
or world.pot_shuffle[player] or world.bush_shuffle[player]
|
|
||||||
or world.killable_thieves[player])
|
|
||||||
|
|
||||||
def generate_output(self, output_directory: str):
|
def generate_output(self, output_directory: str):
|
||||||
multiworld = self.multiworld
|
multiworld = self.multiworld
|
||||||
|
|
Loading…
Reference in New Issue