157 lines
6.9 KiB
Python
157 lines
6.9 KiB
Python
import itertools
|
|
from collections import Counter
|
|
from typing import Dict, List, NamedTuple, Optional, Set
|
|
|
|
from BaseClasses import Item, ItemClassification, MultiWorld
|
|
from .Options import BossesAsChecks, VictoryCondition
|
|
|
|
|
|
class ItemData(NamedTuple):
|
|
code: Optional[int]
|
|
group: str
|
|
classification: ItemClassification = ItemClassification.progression
|
|
required_num: int = 0
|
|
|
|
|
|
class NoitaItem(Item):
|
|
game: str = "Noita"
|
|
|
|
|
|
def create_item(player: int, name: str) -> Item:
|
|
item_data = item_table[name]
|
|
return NoitaItem(name, item_data.classification, item_data.code, player)
|
|
|
|
|
|
def create_fixed_item_pool() -> List[str]:
|
|
required_items: Dict[str, int] = {name: data.required_num for name, data in item_table.items()}
|
|
return list(Counter(required_items).elements())
|
|
|
|
|
|
def create_orb_items(victory_condition: VictoryCondition) -> List[str]:
|
|
orb_count = 0
|
|
if victory_condition == VictoryCondition.option_pure_ending:
|
|
orb_count = 11
|
|
elif victory_condition == VictoryCondition.option_peaceful_ending:
|
|
orb_count = 33
|
|
return ["Orb" for _ in range(orb_count)]
|
|
|
|
|
|
def create_spatial_awareness_item(bosses_as_checks: BossesAsChecks) -> List[str]:
|
|
return ["Spatial Awareness Perk"] if bosses_as_checks.value >= BossesAsChecks.option_all_bosses else []
|
|
|
|
|
|
def create_kantele(victory_condition: VictoryCondition) -> List[str]:
|
|
return ["Kantele"] if victory_condition.value >= VictoryCondition.option_pure_ending else []
|
|
|
|
|
|
def create_random_items(multiworld: MultiWorld, player: int, random_count: int) -> List[str]:
|
|
filler_pool = filler_weights.copy()
|
|
if multiworld.bad_effects[player].value == 0:
|
|
del filler_pool["Trap"]
|
|
|
|
return multiworld.random.choices(
|
|
population=list(filler_pool.keys()),
|
|
weights=list(filler_pool.values()),
|
|
k=random_count
|
|
)
|
|
|
|
|
|
def create_all_items(multiworld: MultiWorld, player: int) -> None:
|
|
sum_locations = len(multiworld.get_unfilled_locations(player))
|
|
|
|
itempool = (
|
|
create_fixed_item_pool()
|
|
+ create_orb_items(multiworld.victory_condition[player])
|
|
+ create_spatial_awareness_item(multiworld.bosses_as_checks[player])
|
|
+ create_kantele(multiworld.victory_condition[player])
|
|
)
|
|
|
|
random_count = sum_locations - len(itempool)
|
|
itempool += create_random_items(multiworld, player, random_count)
|
|
|
|
multiworld.itempool += [create_item(player, name) for name in itempool]
|
|
|
|
|
|
# 110000 - 110032
|
|
item_table: Dict[str, ItemData] = {
|
|
"Trap": ItemData(110000, "Traps", ItemClassification.trap),
|
|
"Extra Max HP": ItemData(110001, "Pickups", ItemClassification.useful),
|
|
"Spell Refresher": ItemData(110002, "Pickups", ItemClassification.filler),
|
|
"Potion": ItemData(110003, "Items", ItemClassification.filler),
|
|
"Gold (200)": ItemData(110004, "Gold", ItemClassification.filler),
|
|
"Gold (1000)": ItemData(110005, "Gold", ItemClassification.filler),
|
|
"Wand (Tier 1)": ItemData(110006, "Wands", ItemClassification.useful),
|
|
"Wand (Tier 2)": ItemData(110007, "Wands", ItemClassification.useful),
|
|
"Wand (Tier 3)": ItemData(110008, "Wands", ItemClassification.useful),
|
|
"Wand (Tier 4)": ItemData(110009, "Wands", ItemClassification.useful),
|
|
"Wand (Tier 5)": ItemData(110010, "Wands", ItemClassification.useful),
|
|
"Wand (Tier 6)": ItemData(110011, "Wands", ItemClassification.useful),
|
|
"Kantele": ItemData(110012, "Wands", ItemClassification.useful),
|
|
"Fire Immunity Perk": ItemData(110013, "Perks", ItemClassification.progression, 1),
|
|
"Toxic Immunity Perk": ItemData(110014, "Perks", ItemClassification.progression, 1),
|
|
"Explosion Immunity Perk": ItemData(110015, "Perks", ItemClassification.progression, 1),
|
|
"Melee Immunity Perk": ItemData(110016, "Perks", ItemClassification.progression, 1),
|
|
"Electricity Immunity Perk": ItemData(110017, "Perks", ItemClassification.progression, 1),
|
|
"Tinker with Wands Everywhere Perk": ItemData(110018, "Perks", ItemClassification.progression, 1),
|
|
"All-Seeing Eye Perk": ItemData(110019, "Perks", ItemClassification.progression, 1),
|
|
"Spatial Awareness Perk": ItemData(110020, "Perks", ItemClassification.progression),
|
|
"Extra Life Perk": ItemData(110021, "Repeatable Perks", ItemClassification.useful),
|
|
"Orb": ItemData(110022, "Orbs", ItemClassification.progression_skip_balancing),
|
|
"Random Potion": ItemData(110023, "Items", ItemClassification.filler),
|
|
"Secret Potion": ItemData(110024, "Items", ItemClassification.filler),
|
|
"Powder Pouch": ItemData(110025, "Items", ItemClassification.filler),
|
|
"Chaos Die": ItemData(110026, "Items", ItemClassification.filler),
|
|
"Greed Die": ItemData(110027, "Items", ItemClassification.filler),
|
|
"Kammi": ItemData(110028, "Items", ItemClassification.filler),
|
|
"Refreshing Gourd": ItemData(110029, "Items", ItemClassification.filler),
|
|
"Sädekivi": ItemData(110030, "Items", ItemClassification.filler),
|
|
"Broken Wand": ItemData(110031, "Items", ItemClassification.filler),
|
|
|
|
}
|
|
|
|
filler_weights: Dict[str, int] = {
|
|
"Trap": 15,
|
|
"Extra Max HP": 25,
|
|
"Spell Refresher": 20,
|
|
"Potion": 40,
|
|
"Gold (200)": 15,
|
|
"Gold (1000)": 6,
|
|
"Wand (Tier 1)": 10,
|
|
"Wand (Tier 2)": 8,
|
|
"Wand (Tier 3)": 7,
|
|
"Wand (Tier 4)": 6,
|
|
"Wand (Tier 5)": 5,
|
|
"Wand (Tier 6)": 4,
|
|
"Extra Life Perk": 10,
|
|
"Random Potion": 9,
|
|
"Secret Potion": 10,
|
|
"Powder Pouch": 10,
|
|
"Chaos Die": 4,
|
|
"Greed Die": 4,
|
|
"Kammi": 4,
|
|
"Refreshing Gourd": 4,
|
|
"Sädekivi": 3,
|
|
"Broken Wand": 10,
|
|
}
|
|
|
|
|
|
# These helper functions make the comprehensions below more readable
|
|
def get_item_group(item_name: str) -> str:
|
|
return item_table[item_name].group
|
|
|
|
|
|
def item_is_filler(item_name: str) -> bool:
|
|
return item_table[item_name].classification == ItemClassification.filler
|
|
|
|
|
|
def item_is_perk(item_name: str) -> bool:
|
|
return item_table[item_name].group == "Perks"
|
|
|
|
|
|
filler_items: List[str] = list(filter(item_is_filler, item_table.keys()))
|
|
item_name_to_id: Dict[str, int] = {name: data.code for name, data in item_table.items()}
|
|
|
|
item_name_groups: Dict[str, Set[str]] = {
|
|
group: set(item_names) for group, item_names in itertools.groupby(item_table, get_item_group)
|
|
}
|