mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
[OC2] Enabled DLC Option (#1688)
- New OC2 option `DLCOptionSet`, which is a list of DLCs whose levels should or shouldn't be used for entrance randomizer (and mention in documentation). By default, DLC owners now need to enable DLCs in weighted settings. - Throw user-friendly exceptions when contradictory settings are enabled - Slightly relax generation requirements for sphere 1/2 level permutations - Write entrance randomizer info in spoiler log - Skip adding "Dark Green Ramp" to item pool if Kevin Levels are disabled
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
from enum import IntEnum
|
||||
from typing import Callable, Dict, Any, List, Optional
|
||||
from typing import Any, List, Dict, Set, Callable, Optional, TextIO
|
||||
|
||||
from BaseClasses import ItemClassification, CollectionState, Region, Entrance, Location, Tutorial, LocationProgressType
|
||||
from worlds.AutoWorld import World, WebWorld
|
||||
|
||||
from .Overcooked2Levels import Overcooked2Level, Overcooked2GenericLevel, ITEMS_TO_EXCLUDE_IF_NO_DLC
|
||||
from .Overcooked2Levels import Overcooked2Dlc, Overcooked2Level, Overcooked2GenericLevel
|
||||
from .Locations import Overcooked2Location, oc2_location_name_to_id, oc2_location_id_to_name
|
||||
from .Options import overcooked_options, OC2Options, OC2OnToggle, LocationBalancingMode, DeathLinkMode
|
||||
from .Items import item_table, Overcooked2Item, item_name_to_id, item_id_to_name, item_to_unlock_event, item_frequencies
|
||||
from .Items import item_table, Overcooked2Item, item_name_to_id, item_id_to_name, item_to_unlock_event, item_frequencies, dlc_exclusives
|
||||
from .Logic import has_requirements_for_level_star, has_requirements_for_level_access, level_shuffle_factory, is_item_progression, is_useful
|
||||
|
||||
|
||||
@@ -222,17 +222,23 @@ class Overcooked2World(World):
|
||||
|
||||
# Helper Data
|
||||
|
||||
player_name: str
|
||||
level_unlock_counts: Dict[int, int] # level_id, stars to purchase
|
||||
level_mapping: Dict[int, Overcooked2GenericLevel] # level_id, level
|
||||
enabled_dlc: Set[Overcooked2Dlc]
|
||||
|
||||
# Autoworld Hooks
|
||||
|
||||
def generate_early(self):
|
||||
self.player_name = self.multiworld.player_name[self.player]
|
||||
self.options = self.get_options()
|
||||
|
||||
# 0.0 to 1.0 where 1.0 is World Record
|
||||
self.star_threshold_scale = self.options["StarThresholdScale"] / 100.0
|
||||
|
||||
# Parse DLCOptionSet back into enums
|
||||
self.enabled_dlc = {Overcooked2Dlc(x) for x in self.options["DLCOptionSet"]}
|
||||
|
||||
# Generate level unlock requirements such that the levels get harder to unlock
|
||||
# the further the game has progressed, and levels progress radially rather than linearly
|
||||
self.level_unlock_counts = level_unlock_requirement_factory(self.options["StarsToWin"])
|
||||
@@ -244,9 +250,16 @@ class Overcooked2World(World):
|
||||
self.multiworld.random,
|
||||
self.options["PrepLevels"] != PrepLevelMode.excluded,
|
||||
self.options["IncludeHordeLevels"],
|
||||
self.options["KevinLevels"],
|
||||
self.enabled_dlc,
|
||||
self.player_name,
|
||||
)
|
||||
else:
|
||||
self.level_mapping = None
|
||||
if Overcooked2Dlc.STORY not in self.enabled_dlc:
|
||||
raise Exception(f"Invalid OC2 settings({self.player_name}) Need either Level Shuffle disabled or 'Story' DLC enabled")
|
||||
|
||||
self.enabled_dlc = {Overcooked2Dlc.STORY}
|
||||
|
||||
def set_location_priority(self) -> None:
|
||||
priority_locations = self.get_priority_locations()
|
||||
@@ -351,17 +364,23 @@ class Overcooked2World(World):
|
||||
# not used
|
||||
continue
|
||||
|
||||
if not self.options["ShuffleLevelOrder"] and item_name in ITEMS_TO_EXCLUDE_IF_NO_DLC:
|
||||
# skip DLC items if no DLC
|
||||
continue
|
||||
if item_name in dlc_exclusives:
|
||||
if not any(x in dlc_exclusives[item_name] for x in self.enabled_dlc):
|
||||
# Item is always useless with these settings
|
||||
continue
|
||||
|
||||
if not self.options["IncludeHordeLevels"] and item_name in ["Calmer Unbread", "Coin Purse"]:
|
||||
# skip horde-specific items if no horde levels
|
||||
continue
|
||||
|
||||
if not self.options["KevinLevels"] and item_name.startswith("Kevin"):
|
||||
# skip kevin items if no kevin levels
|
||||
continue
|
||||
if not self.options["KevinLevels"]:
|
||||
if item_name.startswith("Kevin"):
|
||||
# skip kevin items if no kevin levels
|
||||
continue
|
||||
|
||||
if item_name == "Dark Green Ramp":
|
||||
# skip dark green ramp if there's no Kevin-1 to reveal it
|
||||
continue
|
||||
|
||||
if is_item_progression(item_name, self.level_mapping, self.options["KevinLevels"]):
|
||||
# progression.append(item_name)
|
||||
@@ -425,7 +444,7 @@ class Overcooked2World(World):
|
||||
# Items get distributed to locations
|
||||
|
||||
def fill_json_data(self) -> Dict[str, Any]:
|
||||
mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.player_name[self.player]}"
|
||||
mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.player_name}"
|
||||
|
||||
# Serialize Level Order
|
||||
story_level_order = dict()
|
||||
@@ -578,6 +597,17 @@ class Overcooked2World(World):
|
||||
def fill_slot_data(self) -> Dict[str, Any]:
|
||||
return self.fill_json_data()
|
||||
|
||||
def write_spoiler(self, spoiler_handle: TextIO) -> None:
|
||||
if not self.options["ShuffleLevelOrder"]:
|
||||
return
|
||||
|
||||
world: Overcooked2World = self.multiworld.worlds[self.player]
|
||||
spoiler_handle.write(f"\n\n{self.player_name}'s Level Order:\n\n")
|
||||
for overworld_id in world.level_mapping:
|
||||
overworld_name = Overcooked2GenericLevel(overworld_id).shortname.split("Story ")[1]
|
||||
kitchen_name = world.level_mapping[overworld_id].shortname
|
||||
spoiler_handle.write(f'{overworld_name} | {kitchen_name}\n')
|
||||
|
||||
|
||||
def level_unlock_requirement_factory(stars_to_win: int) -> Dict[int, int]:
|
||||
level_unlock_counts = dict()
|
||||
|
||||
Reference in New Issue
Block a user