scripts/player_stats.pyΒΆ

Part of Dungeon Explorer.

 1"""Derived stat computation: base + gear + level bonuses."""
 2
 3from .inventory import Inventory
 4
 5
 6def compute_derived_stats(
 7    base_str: int,
 8    base_dex: int,
 9    base_vit: int,
10    base_int: int,
11    level: int,
12    inventory: Inventory,
13    skill_bonuses: dict[str, float] | None = None,
14) -> dict[str, float]:
15    """Compute all derived stats from base attributes + equipped gear + skill passives.
16
17    Returns dict with keys: max_hp, damage, defence, speed, crit_chance,
18    dodge_chance, block_chance, life_steal, hp_on_kill, fire_damage,
19    ice_damage, thorns.
20    """
21    gear = inventory.equipment_stats()
22    sb = skill_bonuses or {}
23
24    str_total = base_str + gear.get("str", 0)
25    dex_total = base_dex + gear.get("dex", 0)
26    vit_total = base_vit + gear.get("vit", 0)
27    int_total = base_int + gear.get("int", 0)
28
29    # Base derived stats from attributes + gear
30    max_hp = 80 + vit_total * 5 + level * 3 + gear.get("max_hp", 0) + sb.get("max_hp", 0)
31    damage = str_total // 2 + gear.get("damage", 0)
32    defence = vit_total // 3 + gear.get("defence", 0) + sb.get("defence", 0)
33    speed = 120.0 + dex_total * 0.5 + gear.get("speed", 0) * 100
34    crit_chance = 0.05 + dex_total * 0.003 + gear.get("crit_chance", 0) + sb.get("crit_chance", 0)
35    dodge_chance = 0.02 + dex_total * 0.002 + gear.get("dodge_chance", 0) + sb.get("dodge_chance", 0)
36    block_chance = gear.get("block_chance", 0) + sb.get("block_chance", 0)
37    life_steal = gear.get("life_steal", 0) + sb.get("life_steal", 0)
38    hp_on_kill = gear.get("hp_on_kill", 0) + sb.get("hp_on_kill", 0)
39    spell_power = int_total * 0.8 + gear.get("spell_power", 0)
40
41    # Apply multiplicative skill bonuses
42    damage_mult = 1.0 + sb.get("damage_mult", 0)
43    damage = int(damage * damage_mult)
44    speed *= 1.0 + sb.get("speed", 0)
45    spell_power *= 1.0 + sb.get("spell_power", 0)
46
47    stats = {
48        # Core
49        "str": str_total,
50        "dex": dex_total,
51        "vit": vit_total,
52        "int": int_total,
53        # Derived
54        "max_hp": max_hp,
55        "damage": damage,
56        "defence": defence,
57        "speed": speed,
58        "crit_chance": crit_chance,
59        "dodge_chance": dodge_chance,
60        "block_chance": block_chance,
61        "life_steal": life_steal,
62        "hp_on_kill": hp_on_kill,
63        # Elemental
64        "fire_damage": gear.get("fire_damage", 0) + sb.get("fire_damage", 0),
65        "ice_damage": gear.get("ice_damage", 0) + sb.get("ice_damage", 0),
66        "thorns": gear.get("thorns", 0) + sb.get("thorns", 0),
67        # Magic
68        "spell_power": spell_power,
69        # Knockback: small base, grows with STR and gear
70        "knockback": 2.0 + str_total * 0.5 + gear.get("knockback", 0),
71    }
72    return stats