Core: cleanup Item classes (#849)
This commit is contained in:
parent
dd6e212519
commit
f6da81ac70
|
@ -1144,31 +1144,21 @@ class ItemClassification(IntFlag):
|
|||
|
||||
|
||||
class Item:
|
||||
location: Optional[Location] = None
|
||||
code: Optional[int] = None # an item with ID None is called an Event, and does not get written to multidata
|
||||
name: str
|
||||
game: str = "Generic"
|
||||
type: str = None
|
||||
__slots__ = ("name", "classification", "code", "player", "location")
|
||||
name: str
|
||||
classification: ItemClassification
|
||||
|
||||
# need to find a decent place for these to live and to allow other games to register texts if they want.
|
||||
pedestal_credit_text: str = "and the Unknown Item"
|
||||
sickkid_credit_text: Optional[str] = None
|
||||
magicshop_credit_text: Optional[str] = None
|
||||
zora_credit_text: Optional[str] = None
|
||||
fluteboy_credit_text: Optional[str] = None
|
||||
|
||||
# hopefully temporary attributes to satisfy legacy LttP code, proper implementation in subclass ALttPItem
|
||||
smallkey: bool = False
|
||||
bigkey: bool = False
|
||||
map: bool = False
|
||||
compass: bool = False
|
||||
code: Optional[int]
|
||||
"""an item with code None is called an Event, and does not get written to multidata"""
|
||||
player: int
|
||||
location: Optional[Location]
|
||||
|
||||
def __init__(self, name: str, classification: ItemClassification, code: Optional[int], player: int):
|
||||
self.name = name
|
||||
self.classification = classification
|
||||
self.player = player
|
||||
self.code = code
|
||||
self.location = None
|
||||
|
||||
@property
|
||||
def hint_text(self) -> str:
|
||||
|
|
|
@ -51,6 +51,11 @@ class ItemData(typing.NamedTuple):
|
|||
flute_boy_credit: typing.Optional[str]
|
||||
hint_text: typing.Optional[str]
|
||||
|
||||
def as_init_dict(self) -> typing.Dict[str, typing.Any]:
|
||||
return {key: getattr(self, key) for key in
|
||||
('classification', 'type', 'item_code', 'pedestal_hint', 'hint_text')}
|
||||
|
||||
|
||||
# Format: Name: (Advancement, Type, ItemCode, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text)
|
||||
item_table = {'Bow': ItemData(IC.progression, None, 0x0B, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'),
|
||||
'Progressive Bow': ItemData(IC.progression, None, 0x64, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
|
||||
|
@ -218,7 +223,7 @@ item_table = {'Bow': ItemData(IC.progression, None, 0x0B, 'You have\nchosen the\
|
|||
'Open Floodgate': ItemData(IC.progression, 'Event', None, None, None, None, None, None, None, None),
|
||||
}
|
||||
|
||||
as_dict_item_table = {name: data._asdict() for name, data in item_table.items()}
|
||||
item_init_table = {name: data.as_init_dict() for name, data in item_table.items()}
|
||||
|
||||
progression_mapping = {
|
||||
"Golden Sword": ("Progressive Sword", 4),
|
||||
|
|
|
@ -2091,7 +2091,9 @@ def write_string_to_rom(rom, target, string):
|
|||
|
||||
|
||||
def write_strings(rom, world, player):
|
||||
from . import ALTTPWorld
|
||||
local_random = world.slot_seeds[player]
|
||||
w: ALTTPWorld = world.worlds[player]
|
||||
|
||||
tt = TextTable()
|
||||
tt.removeUnwantedText()
|
||||
|
@ -2420,7 +2422,8 @@ def write_strings(rom, world, player):
|
|||
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem,
|
||||
True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
tt['mastersword_pedestal_translated'] = pedestal_text
|
||||
pedestal_credit_text = 'and the Hot Air' if pedestalitem is None else pedestalitem.pedestal_credit_text if pedestalitem.pedestal_credit_text is not None else 'and the Unknown Item'
|
||||
pedestal_credit_text = 'and the Hot Air' if pedestalitem is None else \
|
||||
w.pedestal_credit_texts.get(pedestalitem.code, 'and the Unknown Item')
|
||||
|
||||
etheritem = world.get_location('Ether Tablet', player).item
|
||||
ether_text = 'Some Hot Air' if etheritem is None else hint_text(etheritem,
|
||||
|
@ -2448,20 +2451,24 @@ def write_strings(rom, world, player):
|
|||
credits = Credits()
|
||||
|
||||
sickkiditem = world.get_location('Sick Kid', player).item
|
||||
sickkiditem_text = local_random.choice(
|
||||
SickKid_texts) if sickkiditem is None or sickkiditem.sickkid_credit_text is None else sickkiditem.sickkid_credit_text
|
||||
sickkiditem_text = local_random.choice(SickKid_texts) \
|
||||
if sickkiditem is None or sickkiditem.code not in w.sickkid_credit_texts \
|
||||
else w.sickkid_credit_texts[sickkiditem.code]
|
||||
|
||||
zoraitem = world.get_location('King Zora', player).item
|
||||
zoraitem_text = local_random.choice(
|
||||
Zora_texts) if zoraitem is None or zoraitem.zora_credit_text is None else zoraitem.zora_credit_text
|
||||
zoraitem_text = local_random.choice(Zora_texts) \
|
||||
if zoraitem is None or zoraitem.code not in w.zora_credit_texts \
|
||||
else w.zora_credit_texts[zoraitem.code]
|
||||
|
||||
magicshopitem = world.get_location('Potion Shop', player).item
|
||||
magicshopitem_text = local_random.choice(
|
||||
MagicShop_texts) if magicshopitem is None or magicshopitem.magicshop_credit_text is None else magicshopitem.magicshop_credit_text
|
||||
magicshopitem_text = local_random.choice(MagicShop_texts) \
|
||||
if magicshopitem is None or magicshopitem.code not in w.magicshop_credit_texts \
|
||||
else w.magicshop_credit_texts[magicshopitem.code]
|
||||
|
||||
fluteboyitem = world.get_location('Flute Spot', player).item
|
||||
fluteboyitem_text = local_random.choice(
|
||||
FluteBoy_texts) if fluteboyitem is None or fluteboyitem.fluteboy_credit_text is None else fluteboyitem.fluteboy_credit_text
|
||||
fluteboyitem_text = local_random.choice(FluteBoy_texts) \
|
||||
if fluteboyitem is None or fluteboyitem.code not in w.fluteboy_credit_texts \
|
||||
else w.fluteboy_credit_texts[fluteboyitem.code]
|
||||
|
||||
credits.update_credits_line('castle', 0, local_random.choice(KingsReturn_texts))
|
||||
credits.update_credits_line('sanctuary', 0, local_random.choice(Sanctuary_texts))
|
||||
|
|
|
@ -18,19 +18,16 @@ class ALttPLocation(Location):
|
|||
|
||||
class ALttPItem(Item):
|
||||
game: str = "A Link to the Past"
|
||||
type: Optional[str]
|
||||
_pedestal_hint_text: Optional[str]
|
||||
_hint_text: Optional[str]
|
||||
dungeon = None
|
||||
|
||||
def __init__(self, name, player, classification=ItemClassification.filler, type=None, item_code=None, pedestal_hint=None,
|
||||
pedestal_credit=None, sick_kid_credit=None, zora_credit=None, witch_credit=None,
|
||||
flute_boy_credit=None, hint_text=None):
|
||||
def __init__(self, name, player, classification=ItemClassification.filler, type=None, item_code=None,
|
||||
pedestal_hint=None, hint_text=None):
|
||||
super(ALttPItem, self).__init__(name, classification, item_code, player)
|
||||
self.type = type
|
||||
self._pedestal_hint_text = pedestal_hint
|
||||
self.pedestal_credit_text = pedestal_credit
|
||||
self.sickkid_credit_text = sick_kid_credit
|
||||
self.zora_credit_text = zora_credit
|
||||
self.magicshop_credit_text = witch_credit
|
||||
self.fluteboy_credit_text = flute_boy_credit
|
||||
self._hint_text = hint_text
|
||||
|
||||
@property
|
||||
|
|
|
@ -8,7 +8,7 @@ from BaseClasses import Item, CollectionState, Tutorial
|
|||
from .SubClasses import ALttPItem
|
||||
from ..AutoWorld import World, WebWorld, LogicMixin
|
||||
from .Options import alttp_options, smallkey_shuffle
|
||||
from .Items import as_dict_item_table, item_name_groups, item_table, GetBeemizerItem
|
||||
from .Items import item_init_table, item_name_groups, item_table, GetBeemizerItem
|
||||
from .Regions import lookup_name_to_id, create_regions, mark_light_world_regions
|
||||
from .Rules import set_rules
|
||||
from .ItemPool import generate_itempool, difficulties
|
||||
|
@ -124,6 +124,17 @@ class ALTTPWorld(World):
|
|||
required_client_version = (0, 3, 2)
|
||||
web = ALTTPWeb()
|
||||
|
||||
pedestal_credit_texts: typing.Dict[int, str] = \
|
||||
{data.item_code: data.pedestal_credit for data in item_table.values() if data.pedestal_credit}
|
||||
sickkid_credit_texts: typing.Dict[int, str] = \
|
||||
{data.item_code: data.sick_kid_credit for data in item_table.values() if data.sick_kid_credit}
|
||||
zora_credit_texts: typing.Dict[int, str] = \
|
||||
{data.item_code: data.zora_credit for data in item_table.values() if data.zora_credit}
|
||||
magicshop_credit_texts: typing.Dict[int, str] = \
|
||||
{data.item_code: data.witch_credit for data in item_table.values() if data.witch_credit}
|
||||
fluteboy_credit_texts: typing.Dict[int, str] = \
|
||||
{data.item_code: data.flute_boy_credit for data in item_table.values() if data.flute_boy_credit}
|
||||
|
||||
set_rules = set_rules
|
||||
|
||||
create_items = generate_itempool
|
||||
|
@ -400,7 +411,7 @@ class ALTTPWorld(World):
|
|||
multidata["connect_names"][new_name] = multidata["connect_names"][self.world.player_name[self.player]]
|
||||
|
||||
def create_item(self, name: str) -> Item:
|
||||
return ALttPItem(name, self.player, **as_dict_item_table[name])
|
||||
return ALttPItem(name, self.player, **item_init_table[name])
|
||||
|
||||
@classmethod
|
||||
def stage_fill_hook(cls, world, progitempool, nonexcludeditempool, localrestitempool, nonlocalrestitempool,
|
||||
|
|
|
@ -47,13 +47,12 @@ class ArchipIDLEWorld(World):
|
|||
|
||||
item_pool = []
|
||||
for i in range(100):
|
||||
item = Item(
|
||||
item = ArchipIDLEItem(
|
||||
item_table_copy[i],
|
||||
ItemClassification.progression if i < 20 else ItemClassification.filler,
|
||||
self.item_name_to_id[item_table_copy[i]],
|
||||
self.player
|
||||
)
|
||||
item.game = 'ArchipIDLE'
|
||||
item_pool.append(item)
|
||||
|
||||
self.world.itempool += item_pool
|
||||
|
@ -93,6 +92,10 @@ def create_region(world: MultiWorld, player: int, name: str, locations=None, exi
|
|||
return region
|
||||
|
||||
|
||||
class ArchipIDLEItem(Item):
|
||||
game = "ArchipIDLE"
|
||||
|
||||
|
||||
class ArchipIDLELocation(Location):
|
||||
game: str = "ArchipIDLE"
|
||||
|
||||
|
|
|
@ -632,8 +632,9 @@ class HKLocation(Location):
|
|||
|
||||
class HKItem(Item):
|
||||
game = "Hollow Knight"
|
||||
type: str
|
||||
|
||||
def __init__(self, name, advancement, code, type, player: int = None):
|
||||
def __init__(self, name, advancement, code, type: str, player: int = None):
|
||||
if name == "Mimic_Grub":
|
||||
classification = ItemClassification.trap
|
||||
elif type in ("Grub", "DreamWarrior", "Root", "Egg"):
|
||||
|
|
|
@ -6,14 +6,9 @@
|
|||
import typing
|
||||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
from worlds.alttp import ALTTPWorld
|
||||
|
||||
|
||||
# pedestal_credit_text: str = "and the Unknown Item"
|
||||
# sickkid_credit_text: Optional[str] = None
|
||||
# magicshop_credit_text: Optional[str] = None
|
||||
# zora_credit_text: Optional[str] = None
|
||||
# fluteboy_credit_text: Optional[str] = None
|
||||
|
||||
class MeritousLttPText(typing.NamedTuple):
|
||||
pedestal: typing.Optional[str]
|
||||
sickkid: typing.Optional[str]
|
||||
|
@ -143,6 +138,7 @@ LttPCreditsText = {
|
|||
|
||||
class MeritousItem(Item):
|
||||
game: str = "Meritous"
|
||||
type: str
|
||||
|
||||
def __init__(self, name, advancement, code, player):
|
||||
super(MeritousItem, self).__init__(name,
|
||||
|
@ -171,14 +167,6 @@ class MeritousItem(Item):
|
|||
self.type = "Artifact"
|
||||
self.classification = ItemClassification.useful
|
||||
|
||||
if name in LttPCreditsText:
|
||||
lttp = LttPCreditsText[name]
|
||||
self.pedestal_credit_text = f"and the {lttp.pedestal}"
|
||||
self.sickkid_credit_text = lttp.sickkid
|
||||
self.magicshop_credit_text = lttp.magicshop
|
||||
self.zora_credit_text = lttp.zora
|
||||
self.fluteboy_credit_text = lttp.fluteboy
|
||||
|
||||
|
||||
offset = 593_000
|
||||
|
||||
|
@ -217,3 +205,10 @@ item_groups = {
|
|||
"Important Artifacts": ["Shield Boost", "Circuit Booster", "Metabolism", "Dodge Enhancer"],
|
||||
"Crystals": ["Crystals x500", "Crystals x1000", "Crystals x2000"]
|
||||
}
|
||||
|
||||
ALTTPWorld.pedestal_credit_texts.update({item_table[name]: f"and the {texts.pedestal}"
|
||||
for name, texts in LttPCreditsText.items()})
|
||||
ALTTPWorld.sickkid_credit_texts.update({item_table[name]: texts.sickkid for name, texts in LttPCreditsText.items()})
|
||||
ALTTPWorld.magicshop_credit_texts.update({item_table[name]: texts.magicshop for name, texts in LttPCreditsText.items()})
|
||||
ALTTPWorld.zora_credit_texts.update({item_table[name]: texts.zora for name, texts in LttPCreditsText.items()})
|
||||
ALTTPWorld.fluteboy_credit_texts.update({item_table[name]: texts.fluteboy for name, texts in LttPCreditsText.items()})
|
||||
|
|
|
@ -24,6 +24,7 @@ def ap_id_to_oot_data(ap_id):
|
|||
|
||||
class OOTItem(Item):
|
||||
game: str = "Ocarina of Time"
|
||||
type: str
|
||||
|
||||
def __init__(self, name, player, data, event, force_not_advancement):
|
||||
(type, advancement, index, special) = data
|
||||
|
@ -38,7 +39,6 @@ class OOTItem(Item):
|
|||
classification = ItemClassification.progression
|
||||
else:
|
||||
classification = ItemClassification.filler
|
||||
adv = bool(advancement) and not force_not_advancement
|
||||
super(OOTItem, self).__init__(name, classification, oot_data_to_ap_id(data, event), player)
|
||||
self.type = type
|
||||
self.index = index
|
||||
|
@ -47,24 +47,11 @@ class OOTItem(Item):
|
|||
self.price = special.get('price', None) if special else None
|
||||
self.internal = False
|
||||
|
||||
# The playthrough calculation calls a function that uses "sweep_for_events(key_only=True)"
|
||||
# This checks if the item it's looking for is a small key, using the small key property.
|
||||
# Because of overlapping item fields, this means that OoT small keys are technically counted, unless we do this.
|
||||
# This causes them to be double-collected during playthrough and generation.
|
||||
@property
|
||||
def smallkey(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def bigkey(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def dungeonitem(self) -> bool:
|
||||
return self.type in ['SmallKey', 'HideoutSmallKey', 'BossKey', 'GanonBossKey', 'Map', 'Compass']
|
||||
|
||||
|
||||
|
||||
# Progressive: True -> Advancement
|
||||
# False -> Priority
|
||||
# None -> Normal
|
||||
|
|
|
@ -2,6 +2,7 @@ import typing
|
|||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
from .Names import ItemName
|
||||
from worlds.alttp import ALTTPWorld
|
||||
|
||||
|
||||
class ItemData(typing.NamedTuple):
|
||||
|
@ -18,9 +19,6 @@ class SA2BItem(Item):
|
|||
def __init__(self, name, classification: ItemClassification, code: int = None, player: int = None):
|
||||
super(SA2BItem, self).__init__(name, classification, code, player)
|
||||
|
||||
if self.name == ItemName.sonic_light_shoes or self.name == ItemName.shadow_air_shoes:
|
||||
self.pedestal_credit_text = "and the Soap Shoes"
|
||||
|
||||
|
||||
# Separate tables for each type of item.
|
||||
emblems_table = {
|
||||
|
@ -94,3 +92,6 @@ item_table = {
|
|||
}
|
||||
|
||||
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code}
|
||||
|
||||
ALTTPWorld.pedestal_credit_texts[item_table[ItemName.sonic_light_shoes].code] = "and the Soap Shoes"
|
||||
ALTTPWorld.pedestal_credit_texts[item_table[ItemName.shadow_air_shoes].code] = "and the Soap Shoes"
|
||||
|
|
|
@ -5,7 +5,7 @@ import copy
|
|||
import os
|
||||
import threading
|
||||
import base64
|
||||
from typing import Set, List, TextIO
|
||||
from typing import Set, TextIO
|
||||
|
||||
from worlds.sm.variaRandomizer.graph.graph_utils import GraphUtils
|
||||
|
||||
|
@ -735,7 +735,8 @@ class SMLocation(Location):
|
|||
|
||||
class SMItem(Item):
|
||||
game = "Super Metroid"
|
||||
type: str
|
||||
|
||||
def __init__(self, name, classification, type, code, player: int = None):
|
||||
def __init__(self, name, classification, type: str, code, player: int):
|
||||
super(SMItem, self).__init__(name, classification, code, player)
|
||||
self.type = type
|
||||
|
|
|
@ -573,8 +573,10 @@ class SMZ3Location(Location):
|
|||
|
||||
class SMZ3Item(Item):
|
||||
game = "SMZ3"
|
||||
type: ItemType
|
||||
item: Item
|
||||
|
||||
def __init__(self, name, classification, type, code, player: int = None, item=None):
|
||||
def __init__(self, name, classification, type: ItemType, code, player: int, item: Item):
|
||||
super(SMZ3Item, self).__init__(name, classification, code, player)
|
||||
self.type = type
|
||||
self.item = item
|
||||
super(SMZ3Item, self).__init__(name, classification, code, player)
|
||||
|
|
Loading…
Reference in New Issue