Files
echoes-of-the-ash/api/services/status_effects.py

102 lines
3.9 KiB
Python

"""
Status Effects Manager.
Loads status effect definitions from gamedata/status_effects.json.
"""
import json
import os
from typing import Dict, Any, Optional
class StatusEffect:
"""Represents a status effect definition."""
def __init__(self, effect_id: str, data: Dict[str, Any]):
self.id = effect_id
self.icon = data.get('icon', '')
self.name = data.get('name', effect_id.capitalize())
self.description = data.get('description', effect_id.capitalize())
self.type = data.get('type', 'debuff')
class StatusEffectsManager:
"""Manages status effect definitions loaded from JSON."""
def __init__(self, gamedata_path: str = "./gamedata"):
self.effects: Dict[str, StatusEffect] = {}
filepath = os.path.join(gamedata_path, 'status_effects.json')
self._load(filepath)
def _load(self, filepath: str):
"""Load status effects from a JSON file."""
try:
with open(filepath, 'r', encoding='utf-8') as f:
data = json.load(f)
for effect_id, effect_data in data.get('effects', {}).items():
self.effects[effect_id] = StatusEffect(effect_id, effect_data)
print(f"✨ Loaded {len(self.effects)} status effects")
except FileNotFoundError:
print("⚠️ status_effects.json not found")
except Exception as e:
print(f"⚠️ Error loading status_effects.json: {e}")
def get_effect(self, effect_id: str) -> Optional[StatusEffect]:
"""Get a status effect by its ID."""
return self.effects.get(effect_id)
def get_effect_info(self, effect_id: str) -> Dict[str, Any]:
"""Get effect info dict for API responses. Returns a fallback if not found."""
effect = self.effects.get(effect_id)
if effect:
return {
'name': effect.name,
'icon': effect.icon,
'description': effect.description,
'type': effect.type,
}
# Fallback for unknown effects
return {
'name': {'en': effect_id.capitalize(), 'es': effect_id.capitalize()},
'icon': '',
'description': {'en': effect_id.capitalize(), 'es': effect_id.capitalize()},
'type': 'debuff',
}
def resolve_player_effect(self, effect_name: str, effect_icon: str, source: str, skills_manager=None, in_combat: bool = True) -> Dict[str, Any]:
"""
Resolve translated name and description for a player effect.
Tries skill source first, then status_effects.json, then fallback.
"""
translated_name = effect_name
translated_desc = ''
# 1. Try to get from skill source (e.g., "skill:fortify")
if source.startswith('skill:') and skills_manager:
skill_id = source.split(':', 1)[1]
skill_def = skills_manager.get_skill(skill_id)
if skill_def:
translated_name = skill_def.name
translated_desc = skill_def.description
# 2. Try to get from status_effects.json by lowercased effect name
if not translated_desc:
effect_key = effect_name.lower()
effect = self.effects.get(effect_key)
if effect:
translated_name = effect.name
translated_desc = effect.description
# 3. Fallback: wrap the raw name as a translatable dict
if not translated_desc:
translated_desc = {'en': effect_name, 'es': effect_name}
if isinstance(translated_name, str):
translated_name = {'en': translated_name, 'es': translated_name}
return {
'name': translated_name,
'icon': effect_icon or '',
'description': translated_desc,
}
# Module-level singleton
status_effects_manager = StatusEffectsManager()