feat(api): integrate equipment stats into combat damage system

Equipment-Combat Integration:
- Update Stats damage formula from STR//2 to int(STR*0.75) for better scaling
- Add spell_power system for magical weapons (staves, wands)
- Add spell_power_bonus field to Stats model with spell_power property
- Add spell_power field to Item model with is_magical_weapon() method
- Update Character.get_effective_stats() to populate spell_power_bonus

Combatant Model Updates:
- Add weapon property fields (crit_chance, crit_multiplier, damage_type)
- Add elemental weapon support (elemental_damage_type, physical_ratio, elemental_ratio)
- Update serialization to handle new weapon properties

DamageCalculator Refactoring:
- Remove weapon_damage parameter from calculate_physical_damage()
- Use attacker_stats.damage directly (includes weapon bonus)
- Use attacker_stats.spell_power for magical damage calculations

Combat Service Updates:
- Extract weapon properties in _create_combatant_from_character()
- Use stats.damage_bonus for enemy combatants from templates
- Remove hardcoded _get_weapon_damage() method
- Handle elemental weapons with split damage in _execute_attack()

Item Generation Updates:
- Add base_spell_power to BaseItemTemplate dataclass
- Add ARCANE damage type to DamageType enum
- Add magical weapon templates (wizard_staff, arcane_staff, wand, crystal_wand)

Test Updates:
- Update test_stats.py for new damage formula (0.75 scaling)
- Update test_character.py for equipment bonus calculations
- Update test_damage_calculator.py for new API signatures
- Update test_combat_service.py mock fixture for equipped attribute

Tests: 174 passing
This commit is contained in:
2025-11-26 19:54:58 -06:00
parent 4ced1b04df
commit a38906b445
16 changed files with 792 additions and 168 deletions

View File

@@ -13,7 +13,7 @@ from app.models.stats import Stats
from app.models.items import Item
from app.models.skills import PlayerClass, SkillNode
from app.models.effects import Effect
from app.models.enums import EffectType, StatType
from app.models.enums import EffectType, StatType, ItemType
from app.models.origins import Origin
@@ -92,7 +92,11 @@ class Character:
This is the CRITICAL METHOD that combines:
1. Base stats (from character)
2. Equipment bonuses (from equipped items)
2. Equipment bonuses (from equipped items):
- stat_bonuses dict applied to corresponding stats
- Weapon damage added to damage_bonus
- Weapon spell_power added to spell_power_bonus
- Armor defense/resistance added to defense_bonus/resistance_bonus
3. Skill tree bonuses (from unlocked skills)
4. Active effect modifiers (buffs/debuffs)
@@ -100,18 +104,30 @@ class Character:
active_effects: Currently active effects on this character (from combat)
Returns:
Stats instance with all modifiers applied
Stats instance with all modifiers applied (including computed
damage, defense, resistance properties that incorporate bonuses)
"""
# Start with a copy of base stats
effective = self.base_stats.copy()
# Apply equipment bonuses
for item in self.equipped.values():
# Apply stat bonuses from item (e.g., +3 strength)
for stat_name, bonus in item.stat_bonuses.items():
if hasattr(effective, stat_name):
current_value = getattr(effective, stat_name)
setattr(effective, stat_name, current_value + bonus)
# Add weapon damage and spell_power to bonus fields
if item.item_type == ItemType.WEAPON:
effective.damage_bonus += item.damage
effective.spell_power_bonus += item.spell_power
# Add armor defense and resistance to bonus fields
if item.item_type == ItemType.ARMOR:
effective.defense_bonus += item.defense
effective.resistance_bonus += item.resistance
# Apply skill tree bonuses
skill_bonuses = self._get_skill_bonuses()
for stat_name, bonus in skill_bonuses.items():