102 lines
3.9 KiB
Python
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()
|