Mi2dRPGamEng/engine/dev_tools.py

55 lines
2.2 KiB
Python

from __future__ import annotations
import uuid
from dataclasses import dataclass, field
from engine.character import Character
from engine.defs import DefRegistry
from engine.item import ItemInstance
@dataclass
class DevSpawnMenu:
"""Dev-mode-only cheat tool: cycle through every loaded item def and materialize one
straight into the player's inventory (first free-fitting slot). Gated off in normal play by
engine/dev_config.py::DevConfig.enabled - see main.py's dev_spawn_object handling.
No world floor-item system exists in this engine yet (items only ever live in an Inventory,
or worn/held on a Character), so "spawning" here means "into inventory", not placing a loose
item on the ground - that's a bigger feature this doesn't attempt.
"""
registry: DefRegistry
item_ids: list[str] = field(default_factory=list)
selected_index: int = 0
def __post_init__(self) -> None:
if not self.item_ids:
# secret items (see ItemDef.secret, e.g. a one-off vanity implant) are deliberately
# left out of the cycle - they still work fine if granted some other way, they just
# aren't discoverable through this menu.
self.item_ids = sorted(def_id for def_id, item_def in self.registry.item_defs.items() if not item_def.secret)
def cycle(self, delta: int) -> None:
if self.item_ids:
self.selected_index = (self.selected_index + delta) % len(self.item_ids)
def selected_item_id(self) -> str | None:
if not self.item_ids:
return None
return self.item_ids[self.selected_index]
def spawn_into(self, character: Character) -> bool:
"""Returns whether it actually fit - a no-op (False) if the character has no inventory
or the selected item has nowhere left to go.
"""
item_id = self.selected_item_id()
if item_id is None or character.inventory is None:
return False
item_def = self.registry.get_item_def(item_id)
slot = character.inventory.find_first_fit(item_def)
if slot is None:
return False
instance = ItemInstance(f"dev-spawn-{uuid.uuid4().hex[:8]}", item_id)
return character.inventory.place(instance, item_def, *slot)