mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
The Witness: v4 Content Update (#1338)
## New Features: - EP Shuffle (Individual or Obelisk Sides, with varying difficulty levels) - Ability to play without Puzzle Randomization (I.e. vanilla + AP layer) - Pet the Dog to get a Puzzle Skip :) (No, really.) ## Changes: - Starting inventory behavior improved (Consider starting items like doors and lasers logically even if they aren't part of the mode) - Audio Log hint system improved (On low hint counts, you will no longer get the same locations hinted every time, i.e. always hints are shuffled) ## Fixes: - Many fixes to symbol requirements - Fixes to "shuffle_postgame" (What checks are evaluated as "postgame" in specific modes) - Logically irrelevant doors are now "useful" instead of "progression"
This commit is contained in:
@@ -51,6 +51,8 @@ class StaticWitnessItems:
|
||||
|
||||
ALL_JUNK_ITEMS = set(BONUS_WEIGHTS.keys()) | set(TRAP_WEIGHTS.keys())
|
||||
|
||||
ITEM_ID_TO_DOOR_HEX_ALL = dict()
|
||||
|
||||
def __init__(self):
|
||||
item_tab = dict()
|
||||
|
||||
@@ -62,6 +64,13 @@ class StaticWitnessItems:
|
||||
|
||||
self.ITEM_NAME_GROUPS.setdefault("Symbols", set()).add(item[0])
|
||||
|
||||
for progressive, item_list in StaticWitnessLogic.PROGRESSIVE_TO_ITEMS.items():
|
||||
if not item_list:
|
||||
continue
|
||||
|
||||
if item_list[0] in self.ITEM_NAME_GROUPS.setdefault("Symbols", set()):
|
||||
self.ITEM_NAME_GROUPS.setdefault("Symbols", set()).add(progressive)
|
||||
|
||||
for item in StaticWitnessLogic.ALL_DOOR_ITEMS:
|
||||
item_tab[item[0]] = ItemData(158000 + item[1], True, False)
|
||||
|
||||
@@ -91,6 +100,9 @@ class StaticWitnessItems:
|
||||
for key, item in item_tab.items():
|
||||
self.ALL_ITEM_TABLE[key] = item
|
||||
|
||||
for door in StaticWitnessLogic.ALL_DOOR_ITEMS:
|
||||
self.ITEM_ID_TO_DOOR_HEX_ALL[door[1] + 158000] = {int(door_hex, 16) for door_hex in door[2]}
|
||||
|
||||
|
||||
class WitnessPlayerItems:
|
||||
"""
|
||||
@@ -101,10 +113,33 @@ class WitnessPlayerItems:
|
||||
def code(item_name: str):
|
||||
return StaticWitnessItems.ALL_ITEM_TABLE[item_name].code
|
||||
|
||||
def __init__(self, locat: WitnessPlayerLocations, world: MultiWorld, player: int, player_logic: WitnessPlayerLogic):
|
||||
@staticmethod
|
||||
def is_progression(item_name: str, multiworld: MultiWorld, player: int):
|
||||
useless_doors = {
|
||||
"River Monastery Shortcut (Door)",
|
||||
"Jungle & River Shortcuts",
|
||||
"Monastery Shortcut (Door)",
|
||||
"Orchard Second Gate (Door)",
|
||||
}
|
||||
|
||||
if item_name in useless_doors:
|
||||
return False
|
||||
|
||||
ep_doors = {
|
||||
"Monastery Garden Entry (Door)",
|
||||
"Monastery Shortcuts",
|
||||
}
|
||||
|
||||
if item_name in ep_doors:
|
||||
return get_option_value(multiworld, player, "shuffle_EPs") != 0
|
||||
|
||||
return True
|
||||
|
||||
def __init__(self, locat: WitnessPlayerLocations, multiworld: MultiWorld, player: int, logic: WitnessPlayerLogic):
|
||||
"""Adds event items after logic changes due to options"""
|
||||
self.EVENT_ITEM_TABLE = dict()
|
||||
self.ITEM_TABLE = copy.copy(StaticWitnessItems.ALL_ITEM_TABLE)
|
||||
|
||||
self.PROGRESSION_TABLE = dict()
|
||||
|
||||
self.ITEM_ID_TO_DOOR_HEX = dict()
|
||||
@@ -116,27 +151,31 @@ class WitnessPlayerItems:
|
||||
|
||||
self.EXTRA_AMOUNTS = {
|
||||
"Functioning Brain": 1,
|
||||
"Puzzle Skip": get_option_value(world, player, "puzzle_skip_amount")
|
||||
"Puzzle Skip": get_option_value(multiworld, player, "puzzle_skip_amount")
|
||||
}
|
||||
|
||||
for k, v in self.ITEM_TABLE.items():
|
||||
if v.progression and not self.is_progression(k, multiworld, player):
|
||||
self.ITEM_TABLE[k] = ItemData(v.code, False, False, never_exclude=True)
|
||||
|
||||
for item in StaticWitnessLogic.ALL_SYMBOL_ITEMS.union(StaticWitnessLogic.ALL_DOOR_ITEMS):
|
||||
if item[0] not in player_logic.PROG_ITEMS_ACTUALLY_IN_THE_GAME:
|
||||
if item[0] not in logic.PROG_ITEMS_ACTUALLY_IN_THE_GAME:
|
||||
del self.ITEM_TABLE[item[0]]
|
||||
if item in StaticWitnessLogic.ALL_SYMBOL_ITEMS:
|
||||
self.SYMBOLS_NOT_IN_THE_GAME.add(StaticWitnessItems.ALL_ITEM_TABLE[item[0]].code)
|
||||
else:
|
||||
if item[0] in StaticWitnessLogic.PROGRESSIVE_TO_ITEMS:
|
||||
self.PROG_ITEM_AMOUNTS[item[0]] = len(player_logic.MULTI_LISTS[item[0]])
|
||||
self.PROG_ITEM_AMOUNTS[item[0]] = len(logic.MULTI_LISTS[item[0]])
|
||||
|
||||
self.PROGRESSION_TABLE[item[0]] = self.ITEM_TABLE[item[0]]
|
||||
|
||||
self.MULTI_LISTS_BY_CODE = dict()
|
||||
|
||||
for item in self.PROG_ITEM_AMOUNTS:
|
||||
multi_list = player_logic.MULTI_LISTS[item]
|
||||
multi_list = logic.MULTI_LISTS[item]
|
||||
self.MULTI_LISTS_BY_CODE[self.code(item)] = [self.code(single_item) for single_item in multi_list]
|
||||
|
||||
for entity_hex, items in player_logic.DOOR_ITEMS_BY_ID.items():
|
||||
for entity_hex, items in logic.DOOR_ITEMS_BY_ID.items():
|
||||
entity_hex_int = int(entity_hex, 16)
|
||||
|
||||
self.DOORS.add(entity_hex_int)
|
||||
@@ -145,26 +184,33 @@ class WitnessPlayerItems:
|
||||
item_id = StaticWitnessItems.ALL_ITEM_TABLE[item].code
|
||||
self.ITEM_ID_TO_DOOR_HEX.setdefault(item_id, set()).add(entity_hex_int)
|
||||
|
||||
symbols = is_option_enabled(world, player, "shuffle_symbols")
|
||||
symbols = is_option_enabled(multiworld, player, "shuffle_symbols")
|
||||
|
||||
if "shuffle_symbols" not in the_witness_options.keys():
|
||||
symbols = True
|
||||
|
||||
doors = get_option_value(world, player, "shuffle_doors")
|
||||
doors = get_option_value(multiworld, player, "shuffle_doors")
|
||||
|
||||
if doors and symbols:
|
||||
self.GOOD_ITEMS = []
|
||||
|
||||
if symbols:
|
||||
self.GOOD_ITEMS = [
|
||||
"Progressive Dots", "Black/White Squares", "Symmetry"
|
||||
]
|
||||
elif symbols:
|
||||
self.GOOD_ITEMS = [
|
||||
"Progressive Dots", "Black/White Squares", "Progressive Stars",
|
||||
"Dots", "Black/White Squares", "Stars",
|
||||
"Shapers", "Symmetry"
|
||||
]
|
||||
|
||||
if is_option_enabled(world, player, "shuffle_discarded_panels"):
|
||||
self.GOOD_ITEMS.append("Triangles")
|
||||
if not is_option_enabled(world, player, "disable_non_randomized_puzzles"):
|
||||
if doors:
|
||||
self.GOOD_ITEMS = [
|
||||
"Dots", "Black/White Squares", "Symmetry"
|
||||
]
|
||||
|
||||
if is_option_enabled(multiworld, player, "shuffle_discarded_panels"):
|
||||
if is_option_enabled(multiworld, player, "shuffle_discarded_panels"):
|
||||
if get_option_value(multiworld, player, "puzzle_randomization") == 1:
|
||||
self.GOOD_ITEMS.append("Arrows")
|
||||
else:
|
||||
self.GOOD_ITEMS.append("Triangles")
|
||||
if not is_option_enabled(multiworld, player, "disable_non_randomized_puzzles"):
|
||||
self.GOOD_ITEMS.append("Colored Squares")
|
||||
|
||||
self.GOOD_ITEMS = [
|
||||
@@ -172,11 +218,11 @@ class WitnessPlayerItems:
|
||||
]
|
||||
|
||||
for event_location in locat.EVENT_LOCATION_TABLE:
|
||||
location = player_logic.EVENT_ITEM_PAIRS[event_location]
|
||||
location = logic.EVENT_ITEM_PAIRS[event_location]
|
||||
self.EVENT_ITEM_TABLE[location] = ItemData(None, True, True)
|
||||
self.ITEM_TABLE[location] = ItemData(None, True, True)
|
||||
|
||||
trap_percentage = get_option_value(world, player, "trap_percentage")
|
||||
trap_percentage = get_option_value(multiworld, player, "trap_percentage")
|
||||
|
||||
self.JUNK_WEIGHTS = dict()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user