Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions worlds/tmc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MinishCapOptions,
NonElementDungeons,
PedReward,
FusionAccess,
ShuffleElements,
get_option_data,
)
Expand Down Expand Up @@ -133,6 +134,16 @@ def generate_early(self) -> None:
10, 10 - options.cucco_rounds.value, -1)])
enabled_pools.update([f"goron:{round_num}" for round_num in range(1, options.goron_sets.value + 1)])

# Option correction for fusions:
if options.gold_fusion_access.value in {FusionAccess.option_open, FusionAccess.option_closed}:
options.clouds_kinstone_multiplier.value = 0
options.swamp_kinstone_multiplier.value = 0
options.falls_kinstone_multiplier.value = 0
elif options.gold_fusion_access == FusionAccess.option_combined:
options.swamp_kinstone_multiplier.value = 0
options.falls_kinstone_multiplier.value = 0


# Default dhc_access to closed when it's been set to ped with goal vaati disabled.
# There's too many flags to manage to allow DHC to open after ped completes and vaati is slain.
if options.goal.value == Goal.option_pedestal and options.dhc_access.value == DHCAccess.option_pedestal:
Expand Down
Binary file modified worlds/tmc/data/basepatch.bsdiff
Binary file not shown.
73 changes: 45 additions & 28 deletions worlds/tmc/items.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from dataclasses import dataclass
import math
from typing import TYPE_CHECKING

from BaseClasses import ItemClassification
from .options import DHCAccess, DungeonItem, Goal, ShuffleElements, DungeonWarp, PedReward, DungeonCompasses, DungeonMaps
from .options import DHCAccess, DungeonItem, Goal, ShuffleElements, DungeonWarp, PedReward, DungeonCompasses, DungeonMaps, FusionAccess, MinishCapOptions
from .constants import TMCItem, TMCLocation, MinishCapItem

if TYPE_CHECKING:
Expand Down Expand Up @@ -58,7 +59,7 @@ def pool_bottles() -> list[str]:
return [TMCItem.EMPTY_BOTTLE] * 4


def pool_baseitems() -> list[str]:
def pool_baseitems(world: "MinishCapWorld") -> list[str]:
return [
*[TMCItem.BOMB_BAG] * 4,
TMCItem.REMOTE_BOMB,
Expand Down Expand Up @@ -103,7 +104,7 @@ def pool_baseitems() -> list[str]:
TMCItem.GREEN_BOOK,
TMCItem.BLUE_BOOK,

*(pool_kinstone_gold()),
*(pool_kinstone_gold(world)),
]


Expand Down Expand Up @@ -193,33 +194,49 @@ def pool_smallkeys(world: "MinishCapWorld") -> list[str]:
return keys


def pool_kinstone_gold() -> list[str]:
return [*[TMCItem.KINSTONE_GOLD_CLOUD] * 5, *[TMCItem.KINSTONE_GOLD_SWAMP] * 3, TMCItem.KINSTONE_GOLD_FALLS]
def pool_kinstone_gold(world: "MinishCapWorld") -> list[str]:
options = world.options
kinstones = []
if options.gold_fusion_access.value == FusionAccess.option_combined:
return [TMCItem.KINSTONE_GOLD_CLOUD] * math.ceil(9 / options.clouds_kinstone_multiplier)
# assuming FusionAccess.option_vanilla
kinstones.extend([TMCItem.KINSTONE_GOLD_CLOUD] * math.ceil(5 / options.clouds_kinstone_multiplier))
kinstones.extend([TMCItem.KINSTONE_GOLD_SWAMP] * math.ceil(3 / options.swamp_kinstone_multiplier))
kinstones.append(TMCItem.KINSTONE_GOLD_FALLS)
return kinstones


def pool_kinstone_red() -> list[str]:
def pool_kinstone_red(options: MinishCapOptions) -> list[str]:
return [*[TMCItem.KINSTONE_RED_W] * 9, *[TMCItem.KINSTONE_RED_ANGLE] * 7, *[TMCItem.KINSTONE_RED_E] * 8]


def pool_kinstone_blue() -> list[str]:
def pool_kinstone_blue(options: MinishCapOptions) -> list[str]:
return [*[TMCItem.KINSTONE_BLUE_L] * 9, *[TMCItem.KINSTONE_BLUE_6] * 9]


def pool_kinstone_green() -> list[str]:
def pool_kinstone_green(options: MinishCapOptions) -> list[str]:
return [*[TMCItem.KINSTONE_GREEN_ANGLE] * 17, *[TMCItem.KINSTONE_GREEN_SQUARE] * 16, *[TMCItem.KINSTONE_GREEN_P] * 16]


def get_item_pool(world: "MinishCapWorld") -> list[MinishCapItem]:
player = world.player
multiworld = world.multiworld
item_pool = pool_baseitems()

if world.options.early_weapon.value:
weapon_pool = [TMCItem.PROGRESSIVE_SWORD, TMCItem.SMITHS_SWORD]
if world.options.weapon_bomb.value in {1, 2}:
weapon_pool.extend([TMCItem.BOMB_BAG])
if world.options.weapon_bow.value:
weapon_pool.extend([TMCItem.PROGRESSIVE_BOW, TMCItem.BOW])
options = world.options
item_pool = pool_baseitems(world)

if options.early_weapon.value:
weapon_pool = []
if options.progressive_sword.value:
weapon_pool.append(TMCItem.PROGRESSIVE_SWORD)
else:
weapon_pool.append(TMCItem.SMITHS_SWORD)
if options.weapon_bomb.value in {1, 2}:
weapon_pool.append(TMCItem.BOMB_BAG)
if options.weapon_bow.value:
if options.progressive_bow.value:
weapon_pool.append(TMCItem.PROGRESSIVE_BOW)
else:
weapon_pool.append(TMCItem.BOW)
weapon_choice = world.random.choice(weapon_pool)
multiworld.local_early_items[player][weapon_choice] = 1

Expand All @@ -230,31 +247,31 @@ def get_item_pool(world: "MinishCapWorld") -> list[MinishCapItem]:
item_pool.extend(pool_scroll(world))
item_pool.extend(pool_health(world))

if world.options.dungeon_big_keys.value == DungeonItem.option_anywhere:
if options.dungeon_big_keys.value == DungeonItem.option_anywhere:
item_pool.extend(pool_bigkeys(world))
item_pool.append(TMCItem.BIG_KEY_TOD)
if world.options.dungeon_small_keys.value == DungeonItem.option_anywhere:
if options.dungeon_small_keys.value == DungeonItem.option_anywhere:
item_pool.extend(pool_smallkeys(world))
if world.options.dungeon_compasses.value == DungeonItem.option_anywhere:
if options.dungeon_compasses.value == DungeonItem.option_anywhere:
item_pool.extend(pool_compass(world))
if world.options.dungeon_maps.value == DungeonItem.option_anywhere:
if options.dungeon_maps.value == DungeonItem.option_anywhere:
item_pool.extend(pool_dungeonmaps(world))

if world.options.figurine_amount > 0:
item_pool.extend([TMCItem.FIGURINE] * world.options.figurine_amount.value)
if options.figurine_amount > 0:
item_pool.extend([TMCItem.FIGURINE] * options.figurine_amount.value)

if world.options.ped_reward == PedReward.option_dhc_big_key:
if options.ped_reward == PedReward.option_dhc_big_key:
world.get_location(TMCLocation.PEDESTAL_REQUIREMENT_REWARD).place_locked_item(world.create_item(TMCItem.BIG_KEY_DHC))

# ToD is stupid, need to place the big key manually
if world.options.dungeon_big_keys.value == DungeonItem.option_own_dungeon and \
TMCItem.BIG_KEY_TOD not in world.options.start_inventory_from_pool.value.keys() and \
world.options.dungeon_warp_tod.value == DungeonWarp.option_none:
if options.dungeon_big_keys.value == DungeonItem.option_own_dungeon and \
TMCItem.BIG_KEY_TOD not in options.start_inventory_from_pool.value.keys() and \
options.dungeon_warp_tod.value == DungeonWarp.option_none:
location = world.random.choice([TMCLocation.DROPLETS_ENTRANCE_B2_EAST_ICEBLOCK,
TMCLocation.DROPLETS_ENTRANCE_B2_WEST_ICEBLOCK])
world.get_location(location).place_locked_item(world.create_item(TMCItem.BIG_KEY_TOD))

if not world.options.random_bottle_contents.value:
if not options.random_bottle_contents.value:
item_pool.extend(pool_bottles())
else:
selected_bottles = []
Expand All @@ -265,7 +282,7 @@ def get_item_pool(world: "MinishCapWorld") -> list[MinishCapItem]:

item_pool.extend(selected_bottles)

if world.options.shuffle_elements.value is ShuffleElements.option_anywhere:
if options.shuffle_elements.value is ShuffleElements.option_anywhere:
item_pool.extend(pool_elements())

return [world.create_item(item) for item in item_pool]
Expand Down
153 changes: 145 additions & 8 deletions worlds/tmc/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,19 @@ class GreenFusionAccess(Choice):
class GoldFusionAccess(Choice):
"""How/when are the Gold Kinstone Fusions accessible?

- Closed: Gold Kinstones aren't in the item pool and none of their fusions are accessible
- Vanilla: Gold Kinstones are added to the item pool and their fusions must be completed as normal
- Combined: Same as Vanilla except all Gold Fusions are changed to request only 'Kinstone Cloud Tops'
- Open: Gold Kinstones aren't in the item pool and all of their fusions are accessible
"""
# - Closed: Gold Kinstones aren't in the item pool and none of their fusions are accessible
# - Open: Gold Kinstones aren't in the item pool and all of their fusions are accessible

visibility = Visibility.none
display_name = "Gold Fusion Access"
rich_text_doc = True

value: int
# option_closed = 0
option_vanilla = 1
# option_combined = 2
option_combined = 2
# option_open = 3
default = option_vanilla

Expand Down Expand Up @@ -847,6 +848,106 @@ class RemoteItems(Toggle):
rich_text_doc = True


class CloudKinstoneMultiplier(Range):
"""How many Cloud Kinstones should be added to your bag each time you get 1?
If gold combined kinstones are enabled, this setting will be used for the all gold kinstones.
This also reduces the number of kinstones in the pool to match the amount required rounded up.
Ex, When set to 2 without combined kinstones, there will be 3 Clouds Kinstones in the pool that each give you 2 Clouds Kinstones."""
display_name = "Cloud Kinstone Multiplier"
rich_text_doc = True

default = 1
range_start = 1
range_end = 9


class SwampKinstoneMultiplier(Range):
"""How many Swamp Kinstones should be added to your bag each time you get 1?
This setting is ignored if using combined gold kinstones"""
display_name = "Swamp Kinstone Multiplier"
rich_text_doc = True

default = 1
range_start = 1
range_end = 3


class FallsKinstoneMultiplier(Range):
"""How many Falls Kinstones should be added to your bag each time you get 1?
This setting is ignored if using combined gold kinstones"""
# This is only here for easy access when writing overriding for open/closed fusions and writing to the rom
visibility = Visibility.none
display_name = "Falls Kinstone Multiplier"
rich_text_doc = True

default = 1
range_start = 1
range_end = 1


class DWSKeyMultiplier(Range):
"""How many Small Keys (DWS) should be added to your inventory each time you get 1?"""
display_name = "DWS Key Multiplier"

default = 1
range_start = 1
range_end = 4


class CoFKeyMultiplier(Range):
"""How many Small Keys (CoF) should be added to your inventory each time you get 1?"""
display_name = "CoF Key Multiplier"

default = 1
range_start = 1
range_end = 2


class FoWKeyMultiplier(Range):
"""How many Small Keys (FoW) should be added to your inventory each time you get 1?"""
display_name = "FoW Key Multiplier"

default = 1
range_start = 1
range_end = 4


class ToDKeyMultiplier(Range):
"""How many Small Keys (ToD) should be added to your inventory each time you get 1?"""
display_name = "ToD Key Multiplier"

default = 1
range_start = 1
range_end = 4


class RCKeyMultiplier(Range):
"""How many Small Keys (RC) should be added to your inventory each time you get 1?"""
display_name = "RC Key Multiplier"

default = 1
range_start = 1
range_end = 3


class PoWKeyMultiplier(Range):
"""How many Small Keys (PoW) should be added to your inventory each time you get 1?"""
display_name = "PoW Key Multiplier"

default = 1
range_start = 1
range_end = 6


class DHCKeyMultiplier(Range):
"""How many Small Keys (DHC) should be added to your inventory each time you get 1?"""
display_name = "DHC Key Multiplier"

default = 1
range_start = 1
range_end = 5


@dataclass
class MinishCapOptions(PerGameCommonOptions):
# AP settings / DL settings
Expand Down Expand Up @@ -902,6 +1003,17 @@ class MinishCapOptions(PerGameCommonOptions):
starting_hearts: StartingHearts
heart_containers: HeartContainerAmount
piece_of_hearts: PieceOfHeartAmount
# Multipliers
clouds_kinstone_multiplier: CloudKinstoneMultiplier
swamp_kinstone_multiplier: SwampKinstoneMultiplier
falls_kinstone_multiplier: FallsKinstoneMultiplier
dws_key_multiplier: DWSKeyMultiplier
cof_key_multiplier: CoFKeyMultiplier
fow_key_multiplier: FoWKeyMultiplier
tod_key_multiplier: ToDKeyMultiplier
rc_key_multiplier: RCKeyMultiplier
pow_key_multiplier: PoWKeyMultiplier
dhc_key_multiplier: DHCKeyMultiplier
# Logic Settings
dungeon_warp_dws: WarpDWS
dungeon_warp_cof: WarpCoF
Expand Down Expand Up @@ -1047,17 +1159,27 @@ def get_option_data(world: "MinishCapWorld"):
"wind_crest_castor",
"wind_crest_south_field",
"wind_crest_minish_woods",
"clouds_kinstone_multiplier",
"swamp_kinstone_multiplier",
"falls_kinstone_multiplier",
"dws_key_multiplier",
"cof_key_multiplier",
"fow_key_multiplier",
"tod_key_multiplier",
"rc_key_multiplier",
"pow_key_multiplier",
"dhc_key_multiplier",
"tricks",
]
"""The yaml options that'll be transfered into slot_data for the tracker"""


OPTION_GROUPS = [
OptionGroup("Goal", [Goal, DHCAccess, PedElements, PedSword, PedDungeons, PedFigurines, FigurineAmount]),
# OptionGroup(
# "Fusions",
# [GoldFusionAccess, RedFusionAccess, GreenFusionAccess, BlueFusionAccess],
# ),
OptionGroup(
"Fusions",
[GoldFusionAccess] # , RedFusionAccess, GreenFusionAccess, BlueFusionAccess],
),
OptionGroup(
"Dungeon Shuffle",
[
Expand Down Expand Up @@ -1116,6 +1238,21 @@ def get_option_data(world: "MinishCapWorld"):
WindCrestMinish,
],
),
OptionGroup(
"Item Multipliers",
[
CloudKinstoneMultiplier,
SwampKinstoneMultiplier,

DWSKeyMultiplier,
CoFKeyMultiplier,
FoWKeyMultiplier,
ToDKeyMultiplier,
RCKeyMultiplier,
PoWKeyMultiplier,
DHCKeyMultiplier
]
),
OptionGroup(
"Quality of Life",
[GoronJPPrices, OcarinaOnSelect, BootsOnL, BootsAsMinish, BigOctorokManipulation, ReplicaToDBossDoor],
Expand Down
Loading