Pre-menu-integration snapshot: combat, crafting, status effects, gamedata updates
This commit is contained in:
@@ -3,11 +3,27 @@ Helper utilities for game calculations and common operations.
|
||||
Contains distance calculations, stamina costs, capacity calculations, etc.
|
||||
"""
|
||||
import math
|
||||
from typing import Tuple, List, Dict, Any, Union
|
||||
import random
|
||||
from typing import Tuple, List, Dict, Any, Union, Optional
|
||||
from .. import database as db
|
||||
from ..items import ItemsManager
|
||||
|
||||
|
||||
def calculate_dynamic_status_damage(effects: dict, prefix: str, target: dict) -> Optional[int]:
|
||||
"""Helper to calculate status damage based on percentage over max HP."""
|
||||
if f'{prefix}_percent' in effects:
|
||||
target_max_hp = target.get('max_hp') or target.get('npc_max_hp', 100)
|
||||
pct = effects[f'{prefix}_percent']
|
||||
base_dmg = target_max_hp * pct
|
||||
# +/- 20% deviation
|
||||
min_dmg = max(1, int(base_dmg * 0.8))
|
||||
max_dmg = max(1, int(base_dmg * 1.2))
|
||||
return random.randint(min_dmg, max_dmg)
|
||||
elif f'{prefix}_damage' in effects:
|
||||
return effects[f'{prefix}_damage']
|
||||
return None
|
||||
|
||||
|
||||
def get_locale_string(value: Union[str, Dict[str, str]], lang: str = 'en') -> str:
|
||||
"""Helper to safely get string from i18n object or string."""
|
||||
if isinstance(value, dict):
|
||||
@@ -54,6 +70,8 @@ GAME_MESSAGES = {
|
||||
'pvp_combat_started_broadcast': {'en': "⚔️ PvP combat started between {attacker} and {defender}!", 'es': "⚔️ ¡Combate PvP iniciado entre {attacker} y {defender}!"},
|
||||
'flee_success_text': {'en': "{name} fled from combat!", 'es': "¡{name} huyó del combate!"},
|
||||
'flee_fail_text': {'en': "{name} tried to flee but failed!", 'es': "¡{name} intentó huir pero falló!"},
|
||||
'stunned_status': {'en': "💫 Stunned!", 'es': "💫 ¡Aturdido!"},
|
||||
'npc_stunned_cannot_act': {'en': "💫 {npc_name} is stunned and cannot act!", 'es': "💫 ¡{npc_name} está aturdido y no puede actuar!"},
|
||||
|
||||
# Loot
|
||||
'corpse_name_npc': {'en': "{name} Corpse", 'es': "Cadáver de {name}"},
|
||||
@@ -101,12 +119,16 @@ GAME_MESSAGES = {
|
||||
'item_used': {'en': "Used {name}", 'es': "Usado {name}"},
|
||||
'no_item': {'en': "You don't have this item", 'es': "No tienes este objeto"},
|
||||
'cannot_use': {'en': "This item cannot be used", 'es': "Este objeto no se puede usar"},
|
||||
'cannot_equip_combat': {'en': "Cannot change equipment during combat", 'es': "No puedes cambiar de equipamiento durante el combate"},
|
||||
'cured': {'en': "Cured", 'es': "Curado"},
|
||||
|
||||
# Status Effects
|
||||
'statusDamage': {'en': "You took {damage} damage from status effects", 'es': "Has recibido {damage} de daño por efectos de estado"},
|
||||
'statusHeal': {'en': "You recovered {heal} HP from status effects", 'es': "Has recuperado {heal} vida por efectos de estado"},
|
||||
'diedFromStatus': {'en': "You died from status effects", 'es': "Has muerto por efectos de estado"},
|
||||
|
||||
# Combat Warnings
|
||||
'enemy_charging': {'en': "⚠️ {enemy} is gathering strength for a massive attack!", 'es': "⚠️ ¡{enemy} está reuniendo fuerzas para un ataque masivo!"},
|
||||
}
|
||||
|
||||
def get_game_message(key: str, lang: str = 'en', **kwargs) -> str:
|
||||
@@ -140,6 +162,36 @@ def translate_travel_message(direction: str, location_name: str, lang: str = 'en
|
||||
|
||||
|
||||
import json
|
||||
from typing import List, Dict, Any, Tuple
|
||||
from .. import database as db
|
||||
|
||||
async def get_resolved_player_effects(player_id: int, in_combat: bool = False) -> List[Dict]:
|
||||
"""Helper to fetch and format active player effects for combat payloads."""
|
||||
from ..services.skills import skills_manager
|
||||
from ..services.status_effects import status_effects_manager
|
||||
|
||||
player_effects = []
|
||||
all_effects = await db.get_player_effects(player_id)
|
||||
for eff in all_effects:
|
||||
if eff.get('effect_type') == 'cooldown':
|
||||
continue
|
||||
resolved = status_effects_manager.resolve_player_effect(
|
||||
eff.get('effect_name', ''),
|
||||
eff.get('effect_icon', '⚡'),
|
||||
eff.get('source', ''),
|
||||
skills_manager,
|
||||
in_combat=in_combat
|
||||
)
|
||||
player_effects.append({
|
||||
'name': resolved['name'],
|
||||
'effect_name': eff.get('effect_name', ''), # Needed for frontend state tracking
|
||||
'icon': resolved['icon'],
|
||||
'ticks_remaining': eff.get('ticks_remaining', 0),
|
||||
'damage_per_tick': eff.get('damage_per_tick', 0), # Needed for logic
|
||||
'type': eff.get('effect_type', 'buff'),
|
||||
'description': resolved['description'],
|
||||
})
|
||||
return player_effects
|
||||
|
||||
def create_combat_message(message_type: str, origin: str = "neutral", **data) -> dict:
|
||||
"""Create a structured combat message object.
|
||||
@@ -274,7 +326,7 @@ async def calculate_player_capacity(inventory: List[Dict[str, Any]], items_manag
|
||||
return current_weight, max_weight, current_volume, max_volume
|
||||
|
||||
|
||||
async def reduce_armor_durability(player_id: int, damage_taken: int, items_manager: ItemsManager) -> Tuple[int, List[Dict[str, Any]]]:
|
||||
async def reduce_armor_durability(player_id: int, damage_taken: int, items_manager: ItemsManager, is_defending: bool = False) -> Tuple[int, List[Dict[str, Any]]]:
|
||||
"""
|
||||
Reduce durability of equipped armor pieces when taking damage.
|
||||
Returns: (armor_damage_absorbed, broken_armor_pieces)
|
||||
@@ -311,7 +363,7 @@ async def reduce_armor_durability(player_id: int, damage_taken: int, items_manag
|
||||
armor_absorbed = min(damage_taken // 2, total_armor)
|
||||
|
||||
# Calculate durability loss for each armor piece
|
||||
base_reduction_rate = 0.1
|
||||
base_reduction_rate = 0.2 if is_defending else 0.1
|
||||
broken_armor = []
|
||||
|
||||
for armor in equipped_armor:
|
||||
|
||||
Reference in New Issue
Block a user