New Beemizer implementation, no longer replacing health; leaving that to item pool settings.
This commit is contained in:
parent
5cc8dd2c71
commit
61bef142a3
136
ItemPool.py
136
ItemPool.py
|
@ -2,12 +2,12 @@ from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import Region, RegionType, Location
|
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 Bosses import place_bosses
|
||||||
from Dungeons import get_dungeon_item_pool
|
from Dungeons import get_dungeon_item_pool
|
||||||
from EntranceShuffle import connect_entrance
|
from EntranceShuffle import connect_entrance
|
||||||
from Fill import FillError, fill_restrictive
|
from Fill import FillError, fill_restrictive
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory, trap_replaceable
|
||||||
from Rules import forbid_items_for_player
|
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.
|
# 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.
|
||||||
|
@ -390,27 +390,22 @@ def generate_itempool(world, player: int):
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
next(adv_heart_pieces).advancement = True
|
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 = []
|
progressionitems = []
|
||||||
nonprogressionitems = []
|
nonprogressionitems = []
|
||||||
for item in items:
|
for item in items:
|
||||||
if item.advancement or item.priority or item.type:
|
if item.advancement or item.priority or item.type:
|
||||||
progressionitems.append(item)
|
progressionitems.append(item)
|
||||||
|
elif world.beemizer[player] and item.name in trap_replaceable:
|
||||||
|
if world.random.random() < world.beemizer[item.player] * 0.25:
|
||||||
|
if world.random.random() < (0.5 + world.beemizer[item.player] * 0.1):
|
||||||
|
nonprogressionitems.append(ItemFactory("Bee Trap", player))
|
||||||
|
else:
|
||||||
|
nonprogressionitems.append(ItemFactory("Bee", player))
|
||||||
|
else:
|
||||||
|
nonprogressionitems.append(item)
|
||||||
else:
|
else:
|
||||||
nonprogressionitems.append(beemizer(item))
|
nonprogressionitems.append(item)
|
||||||
world.random.shuffle(nonprogressionitems)
|
world.random.shuffle(nonprogressionitems)
|
||||||
|
|
||||||
if additional_triforce_pieces:
|
if additional_triforce_pieces:
|
||||||
|
@ -446,89 +441,6 @@ def generate_itempool(world, player: int):
|
||||||
set_up_take_anys(world, player) # depends on world.itempool to be set
|
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 = {
|
take_any_locations = {
|
||||||
'Snitch Lady (East)', 'Snitch Lady (West)', 'Bush Covered House', 'Light World Bomb Hut',
|
'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)',
|
'Fortune Teller (Light)', 'Lake Hylia Fortune Teller', 'Lumberjack House', 'Bonk Fairy (Light)',
|
||||||
|
@ -639,32 +551,6 @@ def fill_prizes(world, attempts=15):
|
||||||
raise FillError('Unable to place dungeon prizes')
|
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):
|
def get_pool_core(world, player: int):
|
||||||
progressive = world.progressive[player]
|
progressive = world.progressive[player]
|
||||||
shuffle = world.shuffle[player]
|
shuffle = world.shuffle[player]
|
||||||
|
|
2
Items.py
2
Items.py
|
@ -234,3 +234,5 @@ progression_items = {name for name, data in item_table.items() if type(data[3])
|
||||||
item_name_groups['Everything'] = {name for name, data in item_table.items() if type(data[3]) == int}
|
item_name_groups['Everything'] = {name for name, data in item_table.items() if type(data[3]) == int}
|
||||||
item_name_groups['Progression Items'] = progression_items
|
item_name_groups['Progression Items'] = progression_items
|
||||||
item_name_groups['Non Progression Items'] = item_name_groups['Everything'] - progression_items
|
item_name_groups['Non Progression Items'] = item_name_groups['Everything'] - progression_items
|
||||||
|
|
||||||
|
trap_replaceable = item_name_groups['Rupees'] | {'Arrows (10)', 'Single Bomb', 'Bombs (3)', 'Bombs (10)'}
|
||||||
|
|
112
Shops.py
112
Shops.py
|
@ -5,7 +5,7 @@ import logging
|
||||||
|
|
||||||
from BaseClasses import Location
|
from BaseClasses import Location
|
||||||
from EntranceShuffle import door_addresses
|
from EntranceShuffle import door_addresses
|
||||||
from Items import item_name_groups, item_table, ItemFactory
|
from Items import item_name_groups, item_table, ItemFactory, trap_replaceable
|
||||||
from Utils import int16_as_bytes
|
from Utils import int16_as_bytes
|
||||||
|
|
||||||
logger = logging.getLogger("Shops")
|
logger = logging.getLogger("Shops")
|
||||||
|
@ -328,3 +328,113 @@ shop_generation_types = {
|
||||||
'bottle': [('Small Heart', 10), ('Apple', 50), ('Bee', 10), ('Good Bee', 100), ('Faerie', 100), ('Magic Jar', 100)],
|
'bottle': [('Small Heart', 10), ('Apple', 50), ('Bee', 10), ('Good Bee', 100), ('Faerie', 100), ('Magic Jar', 100)],
|
||||||
'time': [('Red Clock', 100), ('Blue Clock', 200), ('Green Clock', 300)],
|
'time': [('Red Clock', 100), ('Blue Clock', 200), ('Green Clock', 300)],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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, 1, 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 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: Optional[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 item.name in trap_replaceable:
|
||||||
|
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
|
||||||
|
|
|
@ -221,12 +221,12 @@ pot_shuffle:
|
||||||
'on': 0 # Keys, items, and buttons hidden under pots in dungeons are shuffled with other pots in their supertile
|
'on': 0 # Keys, items, and buttons hidden under pots in dungeons are shuffled with other pots in their supertile
|
||||||
'off': 50 # Default pot item locations
|
'off': 50 # Default pot item locations
|
||||||
### End of Enemizer Section ###
|
### End of Enemizer Section ###
|
||||||
beemizer: # Remove items from the global item pool and replace them with single bees and bee traps
|
beemizer: # Remove items from the global item pool and replace them with single bees (fill bottles) and bee traps
|
||||||
0: 50 # No bee traps are placed
|
0: 50 # No bee traps are placed
|
||||||
1: 0 # 25% of the non-essential item pool is replaced with bee traps
|
1: 0 # 25% of rupees, bombs and arrows are replaced with bees, of which 60% are traps and 40% single bees
|
||||||
2: 0 # 60% of the non-essential item pool is replaced with bee traps, of which 20% could be single bees
|
2: 0 # 50% of rupees, bombs and arrows are replaced with bees, of which 70% are traps and 30% single bees
|
||||||
3: 0 # 100% of the non-essential item pool is replaced with bee traps, of which 50% could be single bees
|
3: 0 # 75% of rupees, bombs and arrows are replaced with bees, of which 80% are traps and 20% single bees
|
||||||
4: 0 # 100% of the non-essential item pool is replaced with bee traps
|
4: 0 # 100% of rupees, bombs and arrows are replaced with bees, of which 90% are traps and 10% single bees
|
||||||
### Shop Settings ###
|
### Shop Settings ###
|
||||||
shop_shuffle_slots: # Maximum amount of shop slots to be filled with regular item pool items (such as Moon Pearl)
|
shop_shuffle_slots: # Maximum amount of shop slots to be filled with regular item pool items (such as Moon Pearl)
|
||||||
0: 50
|
0: 50
|
||||||
|
|
Loading…
Reference in New Issue