Files
fallout-venice/src/engine/inventory.py
T

131 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Brique 4 — Équipement / Inventaire
Gestion du poids, consommation d'items, équipement armure/armes.
Carry Weight = 150 + (STR × 10) lbs — Rules Booklet p.12
Consommation nourriture/eau → relie à survival.py (feed/hydrate).
"""
import db
import survival
def get_carry_weight(strength: int) -> int:
# Manuel FR p.52 : 75 + (FOR × 5) kg
return 75 + strength * 5
def get_current_weight(character_id: int, session_id: int) -> float:
items = db.get_inventory(character_id, session_id)
return sum(i["weight"] * i["quantity"] for i in items)
def is_overencumbered(char: dict) -> bool:
max_w = get_carry_weight(char["strength"])
current_w = get_current_weight(char["id"], char["session_id"])
return current_w > max_w
def consume_food(session_id: int, char_id: int, day: int, tick: int,
item_slug: str) -> dict:
"""
Consomme 1 unité de nourriture depuis l'inventaire.
Retourne {"ok": bool, "reason": str, "effect": dict}
"""
items = db.get_inventory(char_id, session_id)
item = next((i for i in items if i["item_slug"] == item_slug and i["item_type"] == "food"), None)
if not item:
return {"ok": False, "reason": f"Item '{item_slug}' absent de l'inventaire"}
if item["quantity"] < 1:
return {"ok": False, "reason": "Quantité insuffisante"}
# Type de nourriture : cooked si hp_heal >= 7 (nourriture cuisinée), soup si slug contient 'soupe'
food_type = "normal"
if "soupe" in item_slug or "bouillon" in item_slug:
food_type = "soup"
elif item.get("hp_heal", 0) >= 7:
food_type = "cooked"
db.remove_item(char_id, session_id, item_slug, 1)
survival.feed_character(session_id, char_id, day, tick, food_type=food_type)
# Soins PV
hp_heal = item.get("hp_heal", 0)
if hp_heal > 0:
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
char = chars[0]
new_hp = min(char["max_hp"], char["hp"] + hp_heal)
db.update_character(char_id, hp=new_hp)
# Radiations
rad_gain = 0
props = item.get("properties") or {}
if isinstance(props, dict) and props.get("irradiated"):
rad_gain = props.get("rad_on_eat", 1)
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
new_rads = chars[0]["rads"] + rad_gain
db.update_character(char_id, rads=new_rads)
db.log_event(
session_id=session_id, day=day, tick=tick,
event_type="inventaire",
description=f"Consomme {item['item_name']} (food_type={food_type}, +{hp_heal}PV, +{rad_gain}RAD)",
actor_id=char_id,
mechanical_effect={"item": item_slug, "hp_heal": hp_heal, "rad": rad_gain},
)
return {"ok": True, "reason": "ok", "effect": {"hp_heal": hp_heal, "rad_gain": rad_gain, "food_type": food_type}}
def consume_drink(session_id: int, char_id: int, day: int, tick: int,
item_slug: str) -> dict:
"""Consomme 1 boisson depuis l'inventaire."""
items = db.get_inventory(char_id, session_id)
item = next((i for i in items if i["item_slug"] == item_slug and i["item_type"] == "drink"), None)
if not item:
return {"ok": False, "reason": f"Item '{item_slug}' absent de l'inventaire"}
water_type = "purified" if "purifie" in item_slug or "purif" in item_slug else "normal"
db.remove_item(char_id, session_id, item_slug, 1)
survival.hydrate_character(session_id, char_id, day, tick, water_type=water_type)
hp_heal = item.get("hp_heal", 0)
if hp_heal > 0:
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
new_hp = min(chars[0]["max_hp"], chars[0]["hp"] + hp_heal)
db.update_character(char_id, hp=new_hp)
props = item.get("properties") or {}
rad_gain = 0
if isinstance(props, dict) and props.get("irradiated"):
rad_gain = props.get("rad_on_drink", 1)
chars = [c for c in db.get_characters(session_id) if c["id"] == char_id]
if chars:
db.update_character(char_id, rads=chars[0]["rads"] + rad_gain)
db.log_event(
session_id=session_id, day=day, tick=tick,
event_type="inventaire",
description=f"Boit {item['item_name']} (water_type={water_type}, +{hp_heal}PV, +{rad_gain}RAD)",
actor_id=char_id,
mechanical_effect={"item": item_slug, "hp_heal": hp_heal, "rad": rad_gain},
)
return {"ok": True, "reason": "ok", "effect": {"hp_heal": hp_heal, "rad_gain": rad_gain}}
def inventory_summary(character_id: int, session_id: int, char: dict) -> str:
"""Résumé texte de l'inventaire pour le MJ LLM."""
items = db.get_inventory(character_id, session_id)
max_w = get_carry_weight(char["strength"])
cur_w = sum(i["weight"] * i["quantity"] for i in items)
lines = [f"Inventaire de {char['name']} ({cur_w:.1f}/{max_w} kg)"]
for i in items:
eq = " [ÉQUIPÉ]" if i.get("is_equipped") else ""
lines.append(f" {i['item_name']} ×{i['quantity']} ({i['item_type']}){eq}")
return "\n".join(lines)