mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
LADX: tarins gift improvement (#3970)
* add groups and a preset * formatting * pull zig's tarin's gift improvements * typing * alias groups for progressive items * change tarins gift option a bit * add bush breakers item group * fix typo * bush_breaker option, respect non_local_items * review suggestions * cleaner thx exempt * Update worlds/ladx/__init__.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * fix gen failures for dungeon shuffle * exclude shovel based on entrance mapping --------- Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
This commit is contained in:
@@ -7,23 +7,12 @@ from ..roomEditor import RoomEditor
|
|||||||
|
|
||||||
|
|
||||||
class StartItem(DroppedKey):
|
class StartItem(DroppedKey):
|
||||||
# We need to give something here that we can use to progress.
|
|
||||||
# FEATHER
|
|
||||||
OPTIONS = [SWORD, SHIELD, POWER_BRACELET, OCARINA, BOOMERANG, MAGIC_ROD, TAIL_KEY, SHOVEL, HOOKSHOT, PEGASUS_BOOTS, MAGIC_POWDER, BOMB]
|
|
||||||
MULTIWORLD = False
|
MULTIWORLD = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(0x2A3)
|
super().__init__(0x2A3)
|
||||||
self.give_bowwow = False
|
self.give_bowwow = False
|
||||||
|
|
||||||
def configure(self, options):
|
|
||||||
if options.bowwow != 'normal':
|
|
||||||
# When we have bowwow mode, we pretend to be a sword for logic reasons
|
|
||||||
self.OPTIONS = [SWORD]
|
|
||||||
self.give_bowwow = True
|
|
||||||
if options.randomstartlocation and options.entranceshuffle != 'none':
|
|
||||||
self.OPTIONS.append(FLIPPERS)
|
|
||||||
|
|
||||||
def patch(self, rom, option, *, multiworld=None):
|
def patch(self, rom, option, *, multiworld=None):
|
||||||
assert multiworld is None
|
assert multiworld is None
|
||||||
|
|
||||||
|
@@ -527,6 +527,20 @@ class InGameHints(DefaultOnToggle):
|
|||||||
display_name = "In-game Hints"
|
display_name = "In-game Hints"
|
||||||
|
|
||||||
|
|
||||||
|
class TarinsGift(Choice):
|
||||||
|
"""
|
||||||
|
[Local Progression] Forces Tarin's gift to be an item that immediately opens up local checks.
|
||||||
|
Has little effect in single player games, and isn't always necessary with randomized entrances.
|
||||||
|
[Bush Breaker] Forces Tarin's gift to be an item that can destroy bushes.
|
||||||
|
[Any Item] Tarin's gift can be any item for any world
|
||||||
|
"""
|
||||||
|
display_name = "Tarin's Gift"
|
||||||
|
option_local_progression = 0
|
||||||
|
option_bush_breaker = 1
|
||||||
|
option_any_item = 2
|
||||||
|
default = option_local_progression
|
||||||
|
|
||||||
|
|
||||||
class StabilizeItemPool(DefaultOffToggle):
|
class StabilizeItemPool(DefaultOffToggle):
|
||||||
"""
|
"""
|
||||||
By default, rupees in the item pool may be randomly swapped with bombs, arrows, powders, or capacity upgrades. This option disables that swapping, which is useful for plando.
|
By default, rupees in the item pool may be randomly swapped with bombs, arrows, powders, or capacity upgrades. This option disables that swapping, which is useful for plando.
|
||||||
@@ -565,6 +579,7 @@ ladx_option_groups = [
|
|||||||
OptionGroup("Miscellaneous", [
|
OptionGroup("Miscellaneous", [
|
||||||
TradeQuest,
|
TradeQuest,
|
||||||
Rooster,
|
Rooster,
|
||||||
|
TarinsGift,
|
||||||
Overworld,
|
Overworld,
|
||||||
TrendyGame,
|
TrendyGame,
|
||||||
InGameHints,
|
InGameHints,
|
||||||
@@ -638,6 +653,7 @@ class LinksAwakeningOptions(PerGameCommonOptions):
|
|||||||
text_mode: TextMode
|
text_mode: TextMode
|
||||||
no_flash: NoFlash
|
no_flash: NoFlash
|
||||||
in_game_hints: InGameHints
|
in_game_hints: InGameHints
|
||||||
|
tarins_gift: TarinsGift
|
||||||
overworld: Overworld
|
overworld: Overworld
|
||||||
stabilize_item_pool: StabilizeItemPool
|
stabilize_item_pool: StabilizeItemPool
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ import os
|
|||||||
import pkgutil
|
import pkgutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import typing
|
import typing
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import bsdiff4
|
import bsdiff4
|
||||||
@@ -206,6 +207,8 @@ class LinksAwakeningWorld(World):
|
|||||||
return Item(event, ItemClassification.progression, None, self.player)
|
return Item(event, ItemClassification.progression, None, self.player)
|
||||||
|
|
||||||
def create_items(self) -> None:
|
def create_items(self) -> None:
|
||||||
|
itempool = []
|
||||||
|
|
||||||
exclude = [item.name for item in self.multiworld.precollected_items[self.player]]
|
exclude = [item.name for item in self.multiworld.precollected_items[self.player]]
|
||||||
|
|
||||||
self.prefill_original_dungeon = [ [], [], [], [], [], [], [], [], [] ]
|
self.prefill_original_dungeon = [ [], [], [], [], [], [], [], [], [] ]
|
||||||
@@ -265,9 +268,9 @@ class LinksAwakeningWorld(World):
|
|||||||
self.prefill_own_dungeons.append(item)
|
self.prefill_own_dungeons.append(item)
|
||||||
self.pre_fill_items.append(item)
|
self.pre_fill_items.append(item)
|
||||||
else:
|
else:
|
||||||
self.multiworld.itempool.append(item)
|
itempool.append(item)
|
||||||
else:
|
else:
|
||||||
self.multiworld.itempool.append(item)
|
itempool.append(item)
|
||||||
|
|
||||||
self.multi_key = self.generate_multi_key()
|
self.multi_key = self.generate_multi_key()
|
||||||
|
|
||||||
@@ -290,21 +293,52 @@ class LinksAwakeningWorld(World):
|
|||||||
# Properly fill locations within dungeon
|
# Properly fill locations within dungeon
|
||||||
location.dungeon = r.dungeon_index
|
location.dungeon = r.dungeon_index
|
||||||
|
|
||||||
# For now, special case first item
|
if self.options.tarins_gift != "any_item":
|
||||||
FORCE_START_ITEM = True
|
self.force_start_item(itempool)
|
||||||
if FORCE_START_ITEM:
|
|
||||||
self.force_start_item()
|
|
||||||
|
|
||||||
def force_start_item(self):
|
|
||||||
|
self.multiworld.itempool += itempool
|
||||||
|
|
||||||
|
def force_start_item(self, itempool):
|
||||||
start_loc = self.multiworld.get_location("Tarin's Gift (Mabe Village)", self.player)
|
start_loc = self.multiworld.get_location("Tarin's Gift (Mabe Village)", self.player)
|
||||||
if not start_loc.item:
|
if not start_loc.item:
|
||||||
possible_start_items = [index for index, item in enumerate(self.multiworld.itempool)
|
"""
|
||||||
if item.player == self.player
|
Find an item that forces progression or a bush breaker for the player, depending on settings.
|
||||||
and item.item_data.ladxr_id in start_loc.ladxr_item.OPTIONS and not item.location]
|
"""
|
||||||
if possible_start_items:
|
def is_possible_start_item(item):
|
||||||
index = self.random.choice(possible_start_items)
|
return item.advancement and item.name not in self.options.non_local_items
|
||||||
start_item = self.multiworld.itempool.pop(index)
|
|
||||||
|
def opens_new_regions(item):
|
||||||
|
collection_state = base_collection_state.copy()
|
||||||
|
collection_state.collect(item)
|
||||||
|
return len(collection_state.reachable_regions[self.player]) > reachable_count
|
||||||
|
|
||||||
|
start_items = [item for item in itempool if is_possible_start_item(item)]
|
||||||
|
self.random.shuffle(start_items)
|
||||||
|
|
||||||
|
if self.options.tarins_gift == "bush_breaker":
|
||||||
|
start_item = next((item for item in start_items if item.name in links_awakening_item_name_groups["Bush Breakers"]), None)
|
||||||
|
|
||||||
|
else: # local_progression
|
||||||
|
entrance_mapping = self.ladxr_logic.world_setup.entrance_mapping
|
||||||
|
# Tail key opens a region but not a location if d1 entrance is not mapped to d1 or d4
|
||||||
|
# exclude it in these cases to avoid fill errors
|
||||||
|
if entrance_mapping['d1'] not in ['d1', 'd4']:
|
||||||
|
start_items = [item for item in start_items if item.name != 'Tail Key']
|
||||||
|
# Exclude shovel unless starting in Mabe Village
|
||||||
|
if entrance_mapping['start_house'] not in ['start_house', 'shop']:
|
||||||
|
start_items = [item for item in start_items if item.name != 'Shovel']
|
||||||
|
base_collection_state = CollectionState(self.multiworld)
|
||||||
|
base_collection_state.update_reachable_regions(self.player)
|
||||||
|
reachable_count = len(base_collection_state.reachable_regions[self.player])
|
||||||
|
start_item = next((item for item in start_items if opens_new_regions(item)), None)
|
||||||
|
|
||||||
|
if start_item:
|
||||||
|
itempool.remove(start_item)
|
||||||
start_loc.place_locked_item(start_item)
|
start_loc.place_locked_item(start_item)
|
||||||
|
else:
|
||||||
|
logging.getLogger("Link's Awakening Logger").warning(f"No {self.options.tarins_gift.current_option_name} available for Tarin's Gift.")
|
||||||
|
|
||||||
|
|
||||||
def get_pre_fill_items(self):
|
def get_pre_fill_items(self):
|
||||||
return self.pre_fill_items
|
return self.pre_fill_items
|
||||||
|
Reference in New Issue
Block a user