131 lines
5.1 KiB
Python
131 lines
5.1 KiB
Python
"""
|
||
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)
|