mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Merge branch 'main' of https://github.com/Berserker66/MultiWorld-Utilities into triforce_changes
This commit is contained in:
170
ItemPool.py
170
ItemPool.py
@@ -2,12 +2,12 @@ from collections import namedtuple
|
||||
import logging
|
||||
|
||||
from BaseClasses import Region, RegionType, Location
|
||||
from Shops import ShopType, Shop, TakeAny, total_shop_slots
|
||||
from Shops import TakeAny, total_shop_slots, set_up_shops, shuffle_shops
|
||||
from Bosses import place_bosses
|
||||
from Dungeons import get_dungeon_item_pool
|
||||
from EntranceShuffle import connect_entrance
|
||||
from Fill import FillError, fill_restrictive
|
||||
from Items import ItemFactory
|
||||
from Items import ItemFactory, GetBeemizerItem
|
||||
from Rules import forbid_items_for_player
|
||||
|
||||
# This file sets the item pools for various modes. Timed modes and triforce hunt are enforced first, and then extra items are specified per mode to fill in the remaining space.
|
||||
@@ -297,24 +297,22 @@ def generate_itempool(world, player: int):
|
||||
|
||||
world.get_location('Ganon', player).event = True
|
||||
world.get_location('Ganon', player).locked = True
|
||||
world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False)
|
||||
world.get_location('Agahnim 1', player).event = True
|
||||
world.get_location('Agahnim 1', player).locked = True
|
||||
world.push_item(world.get_location('Agahnim 2', player), ItemFactory('Beat Agahnim 2', player), False)
|
||||
world.get_location('Agahnim 2', player).event = True
|
||||
world.get_location('Agahnim 2', player).locked = True
|
||||
world.push_item(world.get_location('Dark Blacksmith Ruins', player), ItemFactory('Pick Up Purple Chest', player), False)
|
||||
world.get_location('Dark Blacksmith Ruins', player).event = True
|
||||
world.get_location('Dark Blacksmith Ruins', player).locked = True
|
||||
world.push_item(world.get_location('Frog', player), ItemFactory('Get Frog', player), False)
|
||||
world.get_location('Frog', player).event = True
|
||||
world.get_location('Frog', player).locked = True
|
||||
world.push_item(world.get_location('Missing Smith', player), ItemFactory('Return Smith', player), False)
|
||||
world.get_location('Missing Smith', player).event = True
|
||||
world.get_location('Missing Smith', player).locked = True
|
||||
world.push_item(world.get_location('Floodgate', player), ItemFactory('Open Floodgate', player), False)
|
||||
world.get_location('Floodgate', player).event = True
|
||||
world.get_location('Floodgate', player).locked = True
|
||||
event_pairs = [
|
||||
('Agahnim 1', 'Beat Agahnim 1'),
|
||||
('Agahnim 2', 'Beat Agahnim 2'),
|
||||
('Dark Blacksmith Ruins', 'Pick Up Purple Chest'),
|
||||
('Frog', 'Get Frog'),
|
||||
('Missing Smith', 'Return Smith'),
|
||||
('Floodgate', 'Open Floodgate'),
|
||||
('Agahnim 1', 'Beat Agahnim 1'),
|
||||
('Flute Activation Spot', 'Activated Flute')
|
||||
]
|
||||
for location_name, event_name in event_pairs:
|
||||
location = world.get_location(location_name, player)
|
||||
event = ItemFactory(event_name, player)
|
||||
world.push_item(location, event, False)
|
||||
location.event = location.locked = True
|
||||
|
||||
|
||||
# set up item pool
|
||||
additional_triforce_pieces = 0
|
||||
@@ -375,7 +373,7 @@ def generate_itempool(world, player: int):
|
||||
|
||||
if world.goal[player] == 'icerodhunt':
|
||||
for item in dungeon_items:
|
||||
world.itempool.append(ItemFactory('Nothing', player))
|
||||
world.itempool.append(ItemFactory(GetBeemizerItem(world, player, 'Nothing'), player))
|
||||
world.push_precollected(item)
|
||||
else:
|
||||
world.itempool.extend([item for item in dungeon_items])
|
||||
@@ -390,27 +388,14 @@ def generate_itempool(world, player: int):
|
||||
for i in range(4):
|
||||
next(adv_heart_pieces).advancement = True
|
||||
|
||||
beeweights = {0: {None: 100},
|
||||
1: {None: 75, 'trap': 25},
|
||||
2: {None: 40, 'trap': 40, 'bee': 20},
|
||||
3: {'trap': 50, 'bee': 50},
|
||||
4: {'trap': 100}}
|
||||
|
||||
def beemizer(item):
|
||||
if world.beemizer[item.player] and not item.advancement and not item.priority and not item.type:
|
||||
choice = world.random.choices(list(beeweights[world.beemizer[item.player]].keys()),
|
||||
weights=list(beeweights[world.beemizer[item.player]].values()))[0]
|
||||
return item if not choice else ItemFactory("Bee Trap", player) if choice == 'trap' else ItemFactory("Bee",
|
||||
player)
|
||||
return item
|
||||
|
||||
progressionitems = []
|
||||
nonprogressionitems = []
|
||||
for item in items:
|
||||
if item.advancement or item.priority or item.type:
|
||||
if item.advancement or item.type:
|
||||
progressionitems.append(item)
|
||||
else:
|
||||
nonprogressionitems.append(beemizer(item))
|
||||
nonprogressionitems.append(GetBeemizerItem(world, item.player, item))
|
||||
world.random.shuffle(nonprogressionitems)
|
||||
|
||||
if additional_triforce_pieces:
|
||||
@@ -427,10 +412,10 @@ def generate_itempool(world, player: int):
|
||||
mm_medallion = world.random.choice(['Ether', 'Quake', 'Bombos'])
|
||||
else:
|
||||
mm_medallion = world.required_medallions[player][0]
|
||||
if world.required_medallions[player][0] == "random":
|
||||
if world.required_medallions[player][1] == "random":
|
||||
tr_medallion = world.random.choice(['Ether', 'Quake', 'Bombos'])
|
||||
else:
|
||||
tr_medallion = world.required_medallions[player][0]
|
||||
tr_medallion = world.required_medallions[player][1]
|
||||
world.required_medallions[player] = (mm_medallion, tr_medallion)
|
||||
|
||||
place_bosses(world, player)
|
||||
@@ -446,89 +431,6 @@ def generate_itempool(world, player: int):
|
||||
set_up_take_anys(world, player) # depends on world.itempool to be set
|
||||
|
||||
|
||||
def shuffle_shops(world, items, player: int):
|
||||
option = world.shop_shuffle[player]
|
||||
if 'u' in option:
|
||||
progressive = world.progressive[player]
|
||||
progressive = world.random.choice([True, False]) if progressive == 'random' else progressive == 'on'
|
||||
progressive &= world.goal == 'icerodhunt'
|
||||
new_items = ["Bomb Upgrade (+5)"] * 6
|
||||
new_items.append("Bomb Upgrade (+5)" if progressive else "Bomb Upgrade (+10)")
|
||||
|
||||
if not world.retro[player]:
|
||||
new_items += ["Arrow Upgrade (+5)"] * 6
|
||||
new_items.append("Arrow Upgrade (+5)" if progressive else "Arrow Upgrade (+10)")
|
||||
|
||||
world.random.shuffle(new_items) # Decide what gets tossed randomly if it can't insert everything.
|
||||
|
||||
capacityshop: Shop = None
|
||||
for shop in world.shops:
|
||||
if shop.type == ShopType.UpgradeShop and shop.region.player == player and \
|
||||
shop.region.name == "Capacity Upgrade":
|
||||
shop.clear_inventory()
|
||||
capacityshop = shop
|
||||
|
||||
if world.goal[player] != 'icerodhunt':
|
||||
for i, item in enumerate(items):
|
||||
if "Heart" not in item.name:
|
||||
items[i] = ItemFactory(new_items.pop(), player)
|
||||
if not new_items:
|
||||
break
|
||||
else:
|
||||
logging.warning(f"Not all upgrades put into Player{player}' item pool. Putting remaining items in Capacity Upgrade shop instead.")
|
||||
bombupgrades = sum(1 for item in new_items if 'Bomb Upgrade' in item)
|
||||
arrowupgrades = sum(1 for item in new_items if 'Arrow Upgrade' in item)
|
||||
if bombupgrades:
|
||||
capacityshop.add_inventory(1, 'Bomb Upgrade (+5)', 100, bombupgrades)
|
||||
if arrowupgrades:
|
||||
capacityshop.add_inventory(1, 'Arrow Upgrade (+5)', 100, arrowupgrades)
|
||||
else:
|
||||
for item in new_items:
|
||||
world.push_precollected(ItemFactory(item, player))
|
||||
|
||||
if 'p' in option or 'i' in option:
|
||||
shops = []
|
||||
upgrade_shops = []
|
||||
total_inventory = []
|
||||
for shop in world.shops:
|
||||
if shop.region.player == player:
|
||||
if shop.type == ShopType.UpgradeShop:
|
||||
upgrade_shops.append(shop)
|
||||
elif shop.type == ShopType.Shop:
|
||||
if shop.region.name == 'Potion Shop' and not 'w' in option:
|
||||
# don't modify potion shop
|
||||
pass
|
||||
else:
|
||||
shops.append(shop)
|
||||
total_inventory.extend(shop.inventory)
|
||||
|
||||
if 'p' in option:
|
||||
def price_adjust(price: int) -> int:
|
||||
# it is important that a base price of 0 always returns 0 as new price!
|
||||
adjust = 2 if price < 100 else 5
|
||||
return int((price / adjust) * (0.5 + world.random.random() * 1.5)) * adjust
|
||||
|
||||
def adjust_item(item):
|
||||
if item:
|
||||
item["price"] = price_adjust(item["price"])
|
||||
item['replacement_price'] = price_adjust(item["price"])
|
||||
|
||||
for item in total_inventory:
|
||||
adjust_item(item)
|
||||
for shop in upgrade_shops:
|
||||
for item in shop.inventory:
|
||||
adjust_item(item)
|
||||
|
||||
if 'i' in option:
|
||||
world.random.shuffle(total_inventory)
|
||||
|
||||
i = 0
|
||||
for shop in shops:
|
||||
slots = shop.slots
|
||||
shop.inventory = total_inventory[i:i + slots]
|
||||
i += slots
|
||||
|
||||
|
||||
take_any_locations = {
|
||||
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
||||
'Fortune Teller (Light)', 'Lake Hylia Fortune Teller', 'Lumberjack House', 'Bonk Fairy (Light)',
|
||||
@@ -639,32 +541,6 @@ def fill_prizes(world, attempts=15):
|
||||
raise FillError('Unable to place dungeon prizes')
|
||||
|
||||
|
||||
def set_up_shops(world, player: int):
|
||||
# TODO: move hard+ mode changes for shields here, utilizing the new shops
|
||||
|
||||
if world.retro[player]:
|
||||
rss = world.get_region('Red Shield Shop', player).shop
|
||||
replacement_items = [['Red Potion', 150], ['Green Potion', 75], ['Blue Potion', 200], ['Bombs (10)', 50],
|
||||
['Blue Shield', 50], ['Small Heart', 10]] # Can't just replace the single arrow with 10 arrows as retro doesn't need them.
|
||||
if world.keyshuffle[player] == "universal":
|
||||
replacement_items.append(['Small Key (Universal)', 100])
|
||||
replacement_item = world.random.choice(replacement_items)
|
||||
rss.add_inventory(2, 'Single Arrow', 80, 1, replacement_item[0], replacement_item[1])
|
||||
rss.locked = True
|
||||
|
||||
if world.keyshuffle[player] == "universal" or world.retro[player]:
|
||||
for shop in world.random.sample([s for s in world.shops if
|
||||
s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player],
|
||||
5):
|
||||
shop.locked = True
|
||||
slots = [0, 0, 1, 1, 2, 2]
|
||||
world.random.shuffle(slots)
|
||||
slots = iter(slots)
|
||||
if world.keyshuffle[player] == "universal":
|
||||
shop.add_inventory(next(slots), 'Small Key (Universal)', 100)
|
||||
if world.retro[player]:
|
||||
shop.push_inventory(next(slots), 'Single Arrow', 80)
|
||||
|
||||
def get_pool_core(world, player: int):
|
||||
progressive = world.progressive[player]
|
||||
shuffle = world.shuffle[player]
|
||||
|
||||
Reference in New Issue
Block a user