66 lines
4.3 KiB
Python
66 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ItemDef:
|
|
id: str
|
|
name: str
|
|
width: int
|
|
height: int
|
|
texture: str | None = None
|
|
color: tuple[int, int, int] = (255, 0, 255)
|
|
stackable: bool = False
|
|
max_stack: int = 1
|
|
clothing_slot: str | None = None # set if this item can be worn (e.g. "torso", "back")
|
|
grants_inventory_size: tuple[int, int] | None = None # e.g. a backpack, when worn
|
|
armor_reduction: float = 0.0 # flat damage reduction while worn (clothing)
|
|
arm_slots_required: int = 0 # sleeved garments only (e.g. a jacket): 0 = no arm-count
|
|
# constraint (hats, backpacks, pants, ...); a garment with more sleeves than the wearer
|
|
# has arms still fits (extras go unused), fewer does not - see Character.wear_item
|
|
compatible_body_types: tuple[str, ...] = () # e.g. ("biped",), ("quadruped",) - which
|
|
# SpeciesDef.body_type values this item can be worn by at all; empty = fits any body type
|
|
weapon_skill: str | None = None # bio skill this weapon's attacks are checked against
|
|
weapon_damage: float = 0.0 # flat bonus added on a successful skill check
|
|
weapon_range: int = 1 # tiles; 1 = melee (adjacent), >1 = ranged (used by shooting)
|
|
projectile_type: str | None = None # e.g. "bullet", "arrow" - what a shield needs to block it
|
|
hands_required: int = 1 # 1 or 2; two-handed items occupy a hand pair when wielded
|
|
shield_block_bonus: float = 0.0 # bonus added to the defender's blocking skill check
|
|
blockable_projectile_types: tuple[str, ...] = () # projectile_types this shield stops
|
|
tool_kind: str | None = None # e.g. "deconstructor", "constructor"
|
|
builds_tile_layer: str | None = None # which layer this material can construct (used with a constructor tool)
|
|
builds_tile_layer_def_id: str | None = None # which def gets placed there
|
|
ammo_type: str | None = None # set on ammo items: "small_caliber", "heavy_caliber", "shotgun_shell", ...
|
|
ranged_knockback: float = 0.0 # ammo items: tiles of knockback dealt on impact
|
|
ammo_damage_bonus: float = 0.0 # ammo items: extra flat damage added to the weapon's own bonus
|
|
compatible_ammo_types: tuple[str, ...] = () # ammo-based weapons: which ammo_types they accept
|
|
magazine_size: int = 0 # ammo-based weapons: base capacity (0 = not ammo-fed, e.g. bow/pistol_basic)
|
|
aim_cone_degrees: float = 0.0 # ranged weapons: base spread; 0 = perfectly accurate
|
|
pellet_count: int = 1 # shotgun-style weapons: independent projectiles fired per shot
|
|
blast_radius: int = 0 # rocket-style weapons: AoE radius in tiles (0 = no AoE)
|
|
attachment_kind: str | None = None # e.g. "scope", "stock", "magazine"
|
|
aimcone_reduction_degrees: float = 0.0 # attachment effect
|
|
magazine_capacity_bonus: int = 0 # attachment effect (e.g. an extended mag)
|
|
melee_knockback: float = 0.0 # melee weapons: base knockback tiles, scaled by attacker strength
|
|
grants_ability: str | None = None # e.g. "time_warp_sphere" - triggered on activation, see resources/logic/abilities.py
|
|
is_implant: bool = False # slotless: installed directly on the character, not held/worn
|
|
consumable: bool = False # single-use: activate_hand unwields (and removes) it after one
|
|
# successful grants_ability cast instead of leaving it wielded, e.g. a stimulant syringe -
|
|
# as opposed to a reusable wand/rod, which just goes on cooldown and stays in hand
|
|
is_hacking_implant: bool = False # an installed implant of this kind both applies
|
|
# hack_bonus/hack_min_roll_percent to every tech check AND lets a bare hand attempt a hack
|
|
# with no wielded hacking_tool at all - see resources/logic/hacking.py::find_hacking_implant
|
|
hack_bonus: float = 0.0 # flat modifier added to a tech skill check's effective_skill
|
|
hack_min_roll_percent: float | None = None # floors the raw d20 roll at this fraction of
|
|
# SKILL_CHECK_DIE (e.g. 0.45 = "never worse than a rolled 9") - None = no floor
|
|
secret: bool = False # excluded from discovery UI (e.g. DevSpawnMenu's cycle list) - still
|
|
# fully functional if granted directly (by def id, save editing, etc.)
|
|
|
|
|
|
class ItemInstance:
|
|
def __init__(self, item_id: str, def_id: str, quantity: int = 1):
|
|
self.item_id = item_id
|
|
self.def_id = def_id
|
|
self.quantity = quantity
|