Core: implement start_inventory_from_pool (#1170)

* Core: implement start_inventory_from_pool

* Factorio/LttP/Subnautica: add start_inventory_from_pool Option
This commit is contained in:
Fabian Dill 2023-04-10 21:13:33 +02:00 committed by GitHub
parent 8d559daa35
commit c7284f90d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 7 deletions

View File

@ -113,7 +113,6 @@ class MultiWorld():
self.dark_world_light_cone = False
self.rupoor_cost = 10
self.aga_randomness = True
self.lock_aga_door_in_escape = False
self.save_and_quit_from_boss = True
self.custom = False
self.customitemarray = []
@ -122,6 +121,7 @@ class MultiWorld():
self.early_items = {player: {} for player in self.player_ids}
self.local_early_items = {player: {} for player in self.player_ids}
self.indirect_connections = {}
self.start_inventory_from_pool = {player: Options.StartInventoryPool({}) for player in range(1, players + 1)}
self.fix_trock_doors = self.AttributeProxy(
lambda player: self.shuffle[player] != 'vanilla' or self.mode[player] == 'inverted')
self.fix_skullwoods_exit = self.AttributeProxy(

29
Main.py
View File

@ -115,6 +115,9 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
for item_name, count in world.start_inventory[player].value.items():
for _ in range(count):
world.push_precollected(world.create_item(item_name, player))
for item_name, count in world.start_inventory_from_pool[player].value.items():
for _ in range(count):
world.push_precollected(world.create_item(item_name, player))
logger.info('Creating World.')
AutoWorld.call_all(world, "create_regions")
@ -149,6 +152,32 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
AutoWorld.call_all(world, "generate_basic")
# remove starting inventory from pool items.
# Because some worlds don't actually create items during create_items this has to be as late as possible.
if any(world.start_inventory_from_pool[player].value for player in world.player_ids):
new_items: List[Item] = []
depletion_pool: Dict[int, Dict[str, int]] = {
player: world.start_inventory_from_pool[player].value.copy() for player in world.player_ids}
for player, items in depletion_pool.items():
player_world: AutoWorld.World = world.worlds[player]
for count in items.values():
new_items.append(player_world.create_filler())
target: int = sum(sum(items.values()) for items in depletion_pool.values())
for item in world.itempool:
if depletion_pool[item.player].get(item.name, 0):
target -= 1
depletion_pool[item.player][item.name] -= 1
# quick abort if we have found all items
if not target:
break
else:
new_items.append(item)
for player, remaining_items in depletion_pool.items():
if remaining_items:
raise Exception(f"{world.get_player_name(player)}"
f" is trying to remove items from their pool that don't exist: {remaining_items}")
world.itempool[:] = new_items
# temporary home for item links, should be moved out of Main
for group_id, group in world.groups.items():
def find_common_pool(players: Set[int], shared_pool: Set[str]) -> Tuple[

View File

@ -897,6 +897,13 @@ class StartInventory(ItemDict):
display_name = "Start Inventory"
class StartInventoryPool(StartInventory):
"""Start with these items and don't place them in the world.
The game decides what the replacement items will be."""
verify_item_name = True
display_name = "Start Inventory from Pool"
class StartHints(ItemSet):
"""Start with these item's locations prefilled into the !hint command."""
display_name = "Start Hints"

View File

@ -1,7 +1,7 @@
import typing
from BaseClasses import MultiWorld
from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, TextChoice, PlandoBosses
from Options import Choice, Range, Option, Toggle, DefaultOnToggle, DeathLink, StartInventoryPool, PlandoBosses
class Logic(Choice):
@ -466,5 +466,6 @@ alttp_options: typing.Dict[str, type(Option)] = {
"beemizer_total_chance": BeemizerTotalChance,
"beemizer_trap_chance": BeemizerTrapChance,
"death_link": DeathLink,
"allow_collect": AllowCollect
"allow_collect": AllowCollect,
"start_inventory_from_pool": StartInventoryPool,
}

View File

@ -1247,8 +1247,8 @@ def patch_rom(world: MultiWorld, rom: LocalRom, player: int, enemized: bool):
# assorted fixes
rom.write_byte(0x1800A2, 0x01 if world.fix_fake_world[
player] else 0x00) # Toggle whether to be in real/fake dark world when dying in a DW dungeon before killing aga1
rom.write_byte(0x180169,
0x01 if world.lock_aga_door_in_escape else 0x00) # Lock or unlock aga tower door during escape sequence.
# Lock or unlock aga tower door during escape sequence.
rom.write_byte(0x180169, 0x00)
if world.mode[player] == 'inverted':
rom.write_byte(0x180169, 0x02) # lock aga/ganon tower door with crystals in inverted
rom.write_byte(0x180171,

View File

@ -2,7 +2,8 @@ from __future__ import annotations
import typing
import datetime
from Options import Choice, OptionDict, OptionSet, ItemDict, Option, DefaultOnToggle, Range, DeathLink, Toggle
from Options import Choice, OptionDict, OptionSet, ItemDict, Option, DefaultOnToggle, Range, DeathLink, Toggle, \
StartInventoryPool
from schema import Schema, Optional, And, Or
# schema helpers
@ -454,6 +455,7 @@ factorio_options: typing.Dict[str, type(Option)] = {
"evolution_trap_increase": EvolutionTrapIncrease,
"death_link": DeathLink,
"energy_link": EnergyLink,
"start_inventory_from_pool": StartInventoryPool,
}
# spoilers below. If you spoil it for yourself, please at least don't spoil it for anyone else.

View File

@ -1,6 +1,6 @@
import typing
from Options import Choice, Range, DeathLink, DefaultOnToggle
from Options import Choice, Range, DeathLink, DefaultOnToggle, StartInventoryPool
from .Creatures import all_creatures, Definitions
@ -104,4 +104,5 @@ options = {
"creature_scans": CreatureScans,
"creature_scan_logic": AggressiveScanLogic,
"death_link": SubnauticaDeathLink,
"start_inventory_from_pool": StartInventoryPool,
}