WIP: Current state before PVP combat investigation
This commit is contained in:
@@ -2,9 +2,11 @@
|
||||
Authentication router.
|
||||
Handles user registration, login, and profile retrieval.
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from fastapi import APIRouter, HTTPException, Depends, status, Request
|
||||
from typing import Dict, Any
|
||||
|
||||
from ..services.helpers import get_game_message
|
||||
|
||||
from ..core.security import create_access_token, hash_password, verify_password, get_current_user
|
||||
from ..services.models import UserRegister, UserLogin
|
||||
from .. import database as db
|
||||
@@ -205,10 +207,12 @@ async def get_account(current_user: Dict[str, Any] = Depends(get_current_user)):
|
||||
@router.post("/change-email")
|
||||
async def change_email(
|
||||
request: "ChangeEmailRequest",
|
||||
req: Request,
|
||||
current_user: Dict[str, Any] = Depends(get_current_user)
|
||||
):
|
||||
"""Change account email address"""
|
||||
from ..services.models import ChangeEmailRequest
|
||||
locale = req.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get account
|
||||
account_id = current_user.get("account_id")
|
||||
@@ -250,7 +254,7 @@ async def change_email(
|
||||
# Update email
|
||||
try:
|
||||
await db.update_account_email(account_id, request.new_email)
|
||||
return {"message": "Email updated successfully", "new_email": request.new_email}
|
||||
return {"message": get_game_message('email_updated', locale), "new_email": request.new_email}
|
||||
except ValueError as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
@@ -261,10 +265,12 @@ async def change_email(
|
||||
@router.post("/change-password")
|
||||
async def change_password(
|
||||
request: "ChangePasswordRequest",
|
||||
req: Request,
|
||||
current_user: Dict[str, Any] = Depends(get_current_user)
|
||||
):
|
||||
"""Change account password"""
|
||||
from ..services.models import ChangePasswordRequest
|
||||
locale = req.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get account
|
||||
account_id = current_user.get("account_id")
|
||||
@@ -305,7 +311,7 @@ async def change_password(
|
||||
new_password_hash = hash_password(request.new_password)
|
||||
await db.update_account_password(account_id, new_password_hash)
|
||||
|
||||
return {"message": "Password updated successfully"}
|
||||
return {"message": get_game_message('password_updated', locale)}
|
||||
|
||||
|
||||
@router.post("/steam-login")
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
Character management router.
|
||||
Handles character creation, selection, and deletion.
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from fastapi import APIRouter, HTTPException, Depends, status, Request
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
|
||||
from ..services.helpers import get_game_message
|
||||
|
||||
from ..core.security import decode_token, create_access_token, security
|
||||
from ..services.models import CharacterCreate, CharacterSelect
|
||||
from .. import database as db
|
||||
@@ -51,10 +53,12 @@ async def list_characters(credentials: HTTPAuthorizationCredentials = Depends(se
|
||||
@router.post("")
|
||||
async def create_character_endpoint(
|
||||
character: CharacterCreate,
|
||||
request: Request,
|
||||
credentials: HTTPAuthorizationCredentials = Depends(security)
|
||||
):
|
||||
"""Create a new character"""
|
||||
token = credentials.credentials
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
payload = decode_token(token)
|
||||
account_id = payload.get("account_id")
|
||||
|
||||
@@ -120,7 +124,7 @@ async def create_character_endpoint(
|
||||
)
|
||||
|
||||
return {
|
||||
"message": "Character created successfully",
|
||||
"message": get_game_message('character_created', locale),
|
||||
"character": {
|
||||
"id": new_character["id"],
|
||||
"name": new_character["name"],
|
||||
@@ -203,10 +207,12 @@ async def select_character(
|
||||
@router.delete("/{character_id}")
|
||||
async def delete_character_endpoint(
|
||||
character_id: int,
|
||||
request: Request,
|
||||
credentials: HTTPAuthorizationCredentials = Depends(security)
|
||||
):
|
||||
"""Delete a character"""
|
||||
token = credentials.credentials
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
payload = decode_token(token)
|
||||
account_id = payload.get("account_id")
|
||||
|
||||
@@ -234,5 +240,5 @@ async def delete_character_endpoint(
|
||||
await db.delete_character(character_id)
|
||||
|
||||
return {
|
||||
"message": f"Character '{character['name']}' deleted successfully"
|
||||
"message": get_game_message('character_deleted', locale, name=character['name'])
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Combat router.
|
||||
Auto-generated from main.py migration.
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from fastapi import APIRouter, HTTPException, Depends, status, Request
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
@@ -12,7 +12,7 @@ import logging
|
||||
|
||||
from ..core.security import get_current_user, security, verify_internal_key
|
||||
from ..services.models import *
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, get_locale_string, create_combat_message
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, get_locale_string, create_combat_message, get_game_message
|
||||
from .. import database as db
|
||||
from ..items import ItemsManager
|
||||
from .. import game_logic
|
||||
@@ -80,6 +80,7 @@ async def get_combat_status(current_user: dict = Depends(get_current_user)):
|
||||
@router.post("/api/game/combat/initiate")
|
||||
async def initiate_combat(
|
||||
req: InitiateCombatRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Start combat with a wandering enemy"""
|
||||
@@ -88,6 +89,9 @@ async def initiate_combat(
|
||||
sys.path.insert(0, '/app')
|
||||
from data.npcs import NPCS
|
||||
|
||||
# Extract locale from Accept-Language header
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Check if already in combat
|
||||
existing_combat = await db.get_active_combat(current_user['id'])
|
||||
if existing_combat:
|
||||
@@ -147,7 +151,7 @@ async def initiate_combat(
|
||||
await manager.send_personal_message(current_user['id'], {
|
||||
"type": "combat_started",
|
||||
"data": {
|
||||
"message": create_combat_message("combat_start", origin="neutral", npc_name=npc_def.name),
|
||||
"messages": [create_combat_message("combat_start", origin="neutral", npc_name=npc_def.name)],
|
||||
"combat": {
|
||||
"npc_id": enemy.npc_id,
|
||||
"npc_name": npc_def.name,
|
||||
@@ -167,7 +171,7 @@ async def initiate_combat(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} entered combat with {get_locale_string(npc_def.name)}",
|
||||
"message": get_game_message('player_entered_combat', locale, player_name=player['name'], npc_name=get_locale_string(npc_def.name, locale)),
|
||||
"action": "combat_started",
|
||||
"player_id": player['id']
|
||||
},
|
||||
@@ -178,7 +182,7 @@ async def initiate_combat(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": create_combat_message("combat_start", origin="neutral", npc_name=npc_def.name),
|
||||
"messages": [create_combat_message("combat_start", origin="neutral", npc_name=npc_def.name)],
|
||||
"combat": {
|
||||
"npc_id": enemy.npc_id,
|
||||
"npc_name": npc_def.name,
|
||||
@@ -194,6 +198,7 @@ async def initiate_combat(
|
||||
@router.post("/api/game/combat/action")
|
||||
async def combat_action(
|
||||
req: CombatActionRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Perform a combat action"""
|
||||
@@ -202,6 +207,9 @@ async def combat_action(
|
||||
sys.path.insert(0, '/app')
|
||||
from data.npcs import NPCS
|
||||
|
||||
# Extract locale from Accept-Language header
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get active combat
|
||||
combat = await db.get_active_combat(current_user['id'])
|
||||
if not combat:
|
||||
@@ -238,7 +246,7 @@ async def combat_action(
|
||||
player = current_user # current_user is already the character dict
|
||||
npc_def = NPCS.get(combat['npc_id'])
|
||||
|
||||
result_message = ""
|
||||
messages = []
|
||||
combat_over = False
|
||||
player_won = False
|
||||
|
||||
@@ -278,12 +286,20 @@ async def combat_action(
|
||||
damage = max(1, base_damage + strength_bonus + level_bonus + weapon_damage + variance)
|
||||
|
||||
if attack_failed:
|
||||
result_message = f"Your attack misses due to heavy encumbrance! "
|
||||
messages.append(create_combat_message(
|
||||
"player_miss",
|
||||
origin="player",
|
||||
reason="encumbrance"
|
||||
))
|
||||
new_npc_hp = combat['npc_hp']
|
||||
else:
|
||||
# Apply damage to NPC
|
||||
new_npc_hp = max(0, combat['npc_hp'] - damage)
|
||||
result_message = f"You attack for {damage} damage! "
|
||||
messages.append(create_combat_message(
|
||||
"player_attack",
|
||||
origin="player",
|
||||
damage=damage
|
||||
))
|
||||
|
||||
# Apply weapon effects
|
||||
if weapon_effects and 'bleeding' in weapon_effects:
|
||||
@@ -292,26 +308,42 @@ async def combat_action(
|
||||
# Apply bleeding effect (would need combat effects table, for now just bonus damage)
|
||||
bleed_damage = bleeding.get('damage', 0)
|
||||
new_npc_hp = max(0, new_npc_hp - bleed_damage)
|
||||
result_message += f"💉 Bleeding effect! +{bleed_damage} damage! "
|
||||
messages.append(create_combat_message(
|
||||
"effect_bleeding",
|
||||
origin="player",
|
||||
damage=bleed_damage
|
||||
))
|
||||
|
||||
# Decrease weapon durability (from unique_item)
|
||||
if weapon_inv_id and inv_item.get('unique_item_id'):
|
||||
new_durability = await db.decrease_unique_item_durability(inv_item['unique_item_id'], 1)
|
||||
if new_durability is None:
|
||||
# Weapon broke (unique_item was deleted, cascades to inventory)
|
||||
result_message += "\n⚠️ Your weapon broke! "
|
||||
messages.append(create_combat_message(
|
||||
"weapon_broke",
|
||||
origin="player",
|
||||
item_name=weapon_def.name
|
||||
))
|
||||
await db.unequip_item(player['id'], 'weapon')
|
||||
|
||||
if new_npc_hp <= 0:
|
||||
# NPC defeated
|
||||
result_message += f"Victory! Defeated {get_locale_string(npc_def.name)}"
|
||||
messages.append(create_combat_message(
|
||||
"victory",
|
||||
origin="neutral",
|
||||
npc_name=npc_def.name
|
||||
))
|
||||
combat_over = True
|
||||
player_won = True
|
||||
|
||||
# Award XP
|
||||
xp_gained = npc_def.xp_reward
|
||||
new_xp = player['xp'] + xp_gained
|
||||
result_message += f"\n+{xp_gained} XP"
|
||||
messages.append(create_combat_message(
|
||||
"xp_gain",
|
||||
origin="player",
|
||||
amount=xp_gained
|
||||
))
|
||||
|
||||
await db.update_player(player['id'], xp=new_xp)
|
||||
|
||||
@@ -321,8 +353,12 @@ async def combat_action(
|
||||
# Check for level up
|
||||
level_up_result = await game_logic.check_and_apply_level_up(player['id'])
|
||||
if level_up_result['leveled_up']:
|
||||
result_message += f"\n🎉 Level Up! You are now level {level_up_result['new_level']}!"
|
||||
result_message += f"\n+{level_up_result['levels_gained']} stat point(s) to spend!"
|
||||
messages.append(create_combat_message(
|
||||
"level_up",
|
||||
origin="player",
|
||||
level=level_up_result['new_level'],
|
||||
stat_points=level_up_result['levels_gained']
|
||||
))
|
||||
|
||||
# Create corpse with loot
|
||||
import json
|
||||
@@ -361,7 +397,7 @@ async def combat_action(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} defeated {npc_def.name}",
|
||||
"message": get_game_message('player_defeated_enemy_broadcast', locale, player_name=player['name'], npc_name=get_locale_string(npc_def.name, locale)),
|
||||
"action": "combat_ended",
|
||||
"player_id": player['id'],
|
||||
"corpse_created": True
|
||||
@@ -373,13 +409,13 @@ async def combat_action(
|
||||
|
||||
else:
|
||||
# NPC's turn - use shared logic
|
||||
npc_attack_message, player_defeated = await game_logic.npc_attack(
|
||||
npc_attack_messages, player_defeated = await game_logic.npc_attack(
|
||||
player['id'],
|
||||
{'npc_hp': new_npc_hp, 'npc_max_hp': combat['npc_max_hp']},
|
||||
npc_def,
|
||||
reduce_armor_durability
|
||||
)
|
||||
result_message += f"\n{npc_attack_message}"
|
||||
messages.extend(npc_attack_messages)
|
||||
|
||||
if player_defeated:
|
||||
combat_over = True
|
||||
@@ -392,7 +428,10 @@ async def combat_action(
|
||||
elif req.action == 'flee':
|
||||
# 50% chance to flee
|
||||
if random.random() < 0.5:
|
||||
result_message = "You successfully fled from combat!"
|
||||
messages.append(create_combat_message(
|
||||
"flee_success",
|
||||
origin="player"
|
||||
))
|
||||
combat_over = True
|
||||
player_won = False # Fled, not won
|
||||
|
||||
@@ -423,7 +462,7 @@ async def combat_action(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} fled from combat",
|
||||
"message": get_game_message('player_fled_broadcast', locale, player_name=player['name']),
|
||||
"action": "combat_fled",
|
||||
"player_id": player['id']
|
||||
},
|
||||
@@ -435,10 +474,20 @@ async def combat_action(
|
||||
# Failed to flee, NPC attacks
|
||||
npc_damage = random.randint(npc_def.damage_min, npc_def.damage_max)
|
||||
new_player_hp = max(0, player['hp'] - npc_damage)
|
||||
result_message = f"Failed to flee! {get_locale_string(npc_def.name)} attacks for {npc_damage} damage!"
|
||||
|
||||
messages.append(create_combat_message(
|
||||
"flee_fail",
|
||||
origin="enemy",
|
||||
npc_name=npc_def.name,
|
||||
damage=npc_damage
|
||||
))
|
||||
|
||||
if new_player_hp <= 0:
|
||||
result_message += "\nYou have been defeated!"
|
||||
messages.append(create_combat_message(
|
||||
"player_defeated",
|
||||
origin="neutral",
|
||||
npc_name=npc_def.name
|
||||
))
|
||||
combat_over = True
|
||||
await db.update_player(player['id'], hp=0, is_dead=True)
|
||||
await db.update_player_statistics(player['id'], deaths=1, failed_flees=1, damage_taken=npc_damage, increment=True)
|
||||
@@ -509,7 +558,7 @@ async def combat_action(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} was defeated in combat",
|
||||
"message": get_game_message('player_defeated_broadcast', locale, player_name=player['name']),
|
||||
"action": "player_died",
|
||||
"player_id": player['id'],
|
||||
"corpse": corpse_data
|
||||
@@ -558,7 +607,7 @@ async def combat_action(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": result_message,
|
||||
"messages": messages,
|
||||
"combat_over": combat_over,
|
||||
"player_won": player_won if combat_over else None,
|
||||
"combat": updated_combat if updated_combat else None,
|
||||
@@ -574,6 +623,7 @@ async def combat_action(
|
||||
@router.post("/api/game/pvp/initiate")
|
||||
async def initiate_pvp_combat(
|
||||
req: PvPCombatInitiateRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Initiate PvP combat with another player"""
|
||||
@@ -582,6 +632,9 @@ async def initiate_pvp_combat(
|
||||
if not attacker:
|
||||
raise HTTPException(status_code=404, detail="Player not found")
|
||||
|
||||
# Extract locale
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Check if attacker is already in combat
|
||||
existing_combat = await db.get_active_combat(attacker['id'])
|
||||
if existing_combat:
|
||||
@@ -637,7 +690,7 @@ async def initiate_pvp_combat(
|
||||
await manager.send_personal_message(attacker['id'], {
|
||||
"type": "combat_started",
|
||||
"data": {
|
||||
"message": f"You have initiated combat with {defender['name']}! They get the first turn.",
|
||||
"message": get_game_message('pvp_initiated_attacker', locale, defender=defender['name']),
|
||||
"pvp_combat": pvp_combat
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
@@ -646,7 +699,7 @@ async def initiate_pvp_combat(
|
||||
await manager.send_personal_message(defender['id'], {
|
||||
"type": "combat_started",
|
||||
"data": {
|
||||
"message": f"{attacker['name']} has challenged you to PvP combat! It's your turn.",
|
||||
"message": get_game_message('pvp_challenged_defender', locale, attacker=attacker['name']),
|
||||
"pvp_combat": pvp_combat
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
@@ -654,7 +707,7 @@ async def initiate_pvp_combat(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"You have initiated combat with {defender['name']}! They get the first turn.",
|
||||
"message": get_game_message('pvp_initiated_attacker', locale, defender=defender['name']),
|
||||
"pvp_combat": pvp_combat
|
||||
}
|
||||
|
||||
@@ -737,11 +790,15 @@ class PvPAcknowledgeRequest(BaseModel):
|
||||
@router.post("/api/game/pvp/acknowledge")
|
||||
async def acknowledge_pvp_combat(
|
||||
req: PvPAcknowledgeRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Acknowledge PvP combat end"""
|
||||
await db.acknowledge_pvp_combat(req.combat_id, current_user['id'])
|
||||
|
||||
# Extract locale from Accept-Language header
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Broadcast to location that player has returned
|
||||
player = current_user # current_user is already the character dict
|
||||
if player:
|
||||
@@ -752,7 +809,7 @@ async def acknowledge_pvp_combat(
|
||||
"data": {
|
||||
"player_id": player['id'],
|
||||
"username": player['name'],
|
||||
"message": f"{player['name']} has returned from PvP combat."
|
||||
"message": get_game_message('player_returned_pvp', locale, player_name=player['name'])
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
},
|
||||
@@ -770,12 +827,16 @@ class PvPCombatActionRequest(BaseModel):
|
||||
@router.post("/api/game/pvp/action")
|
||||
async def pvp_combat_action(
|
||||
req: PvPCombatActionRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Perform a PvP combat action"""
|
||||
import random
|
||||
import time
|
||||
|
||||
# Extract locale
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get PvP combat
|
||||
pvp_combat = await db.get_pvp_combat_by_player(current_user['id'])
|
||||
if not pvp_combat:
|
||||
@@ -795,10 +856,13 @@ async def pvp_combat_action(
|
||||
current_player = attacker if is_attacker else defender
|
||||
opponent = defender if is_attacker else attacker
|
||||
|
||||
result_message = ""
|
||||
messages = []
|
||||
combat_over = False
|
||||
winner_id = None
|
||||
|
||||
# Track the last action string for DB history
|
||||
last_action_text = ""
|
||||
|
||||
if req.action == 'attack':
|
||||
# Calculate damage (similar to PvE)
|
||||
base_damage = 5
|
||||
@@ -822,7 +886,11 @@ async def pvp_combat_action(
|
||||
if inv_item.get('unique_item_id'):
|
||||
new_durability = await db.decrease_unique_item_durability(inv_item['unique_item_id'], 1)
|
||||
if new_durability is None:
|
||||
result_message += "⚠️ Your weapon broke! "
|
||||
messages.append(create_combat_message(
|
||||
"weapon_broke",
|
||||
origin="player",
|
||||
item_name=weapon_def.name
|
||||
))
|
||||
await db.unequip_item(current_player['id'], 'weapon')
|
||||
|
||||
variance = random.randint(-2, 2)
|
||||
@@ -832,24 +900,42 @@ async def pvp_combat_action(
|
||||
armor_absorbed, broken_armor = await reduce_armor_durability(opponent['id'], damage)
|
||||
actual_damage = max(1, damage - armor_absorbed)
|
||||
|
||||
# Structure the attack message
|
||||
messages.append(create_combat_message(
|
||||
"player_attack",
|
||||
origin="player",
|
||||
damage=damage,
|
||||
armor_absorbed=armor_absorbed
|
||||
))
|
||||
|
||||
# Update opponent HP (use actual player HP, not pvp_combat fields)
|
||||
new_opponent_hp = max(0, opponent['hp'] - actual_damage)
|
||||
|
||||
# Update opponent's HP in database
|
||||
await db.update_player(opponent['id'], hp=new_opponent_hp)
|
||||
|
||||
# Store message with attacker's username so both players can see it correctly
|
||||
stored_message = f"{current_player['name']} attacks {opponent['name']} for {damage} damage!"
|
||||
# Construct summary string for DB history/passive player
|
||||
last_action_text = f"{current_player['name']} attacks {opponent['name']} for {damage} damage!"
|
||||
if armor_absorbed > 0:
|
||||
stored_message += f" (Armor absorbed {armor_absorbed})"
|
||||
last_action_text += f" (Armor absorbed {armor_absorbed})"
|
||||
|
||||
for broken in broken_armor:
|
||||
stored_message += f"\n💔 {opponent['name']}'s {broken['emoji']} {broken['name']} broke!"
|
||||
messages.append(create_combat_message(
|
||||
"item_broken",
|
||||
origin="enemy", # Belongs to opponent
|
||||
item_name=broken['name'],
|
||||
emoji=broken['emoji']
|
||||
))
|
||||
last_action_text += f"\n💔 {opponent['name']}'s {broken['emoji']} {broken['name']} broke!"
|
||||
|
||||
# Check if opponent defeated
|
||||
if new_opponent_hp <= 0:
|
||||
stored_message += f"\n🏆 {current_player['name']} has defeated {opponent['name']}!"
|
||||
result_message = "Combat victory!" # Simple message, details in stored_message
|
||||
last_action_text += f"\n🏆 {current_player['name']} has defeated {opponent['name']}!"
|
||||
messages.append(create_combat_message(
|
||||
"victory",
|
||||
origin="neutral",
|
||||
npc_name=opponent['name']
|
||||
))
|
||||
combat_over = True
|
||||
winner_id = current_player['id']
|
||||
|
||||
@@ -921,7 +1007,7 @@ async def pvp_combat_action(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{opponent['name']} was defeated by {current_player['name']} in PvP combat",
|
||||
"message": get_game_message('pvp_defeat_broadcast', locale, opponent=opponent['name'], winner=current_player['name']),
|
||||
"action": "player_died",
|
||||
"player_id": opponent['id'],
|
||||
"corpse": corpse_data
|
||||
@@ -933,8 +1019,7 @@ async def pvp_combat_action(
|
||||
# End PvP combat
|
||||
await db.end_pvp_combat(pvp_combat['id'])
|
||||
else:
|
||||
# Combat continues - don't return detailed message, it's in stored_message
|
||||
result_message = "" # Empty message, frontend will show stored_message from polling
|
||||
# Combat continues
|
||||
|
||||
# Update PvP statistics for attack
|
||||
await db.update_player_statistics(current_player['id'],
|
||||
@@ -953,7 +1038,7 @@ async def pvp_combat_action(
|
||||
updates = {
|
||||
'turn': 'defender' if is_attacker else 'attacker',
|
||||
'turn_started_at': time.time(),
|
||||
'last_action': f"{stored_message}|{time.time()}" # Add timestamp for uniqueness
|
||||
'last_action': f"{last_action_text}|{time.time()}" # Add timestamp for uniqueness
|
||||
}
|
||||
# No need to update HP in pvp_combat - we use player HP directly
|
||||
|
||||
@@ -963,14 +1048,19 @@ async def pvp_combat_action(
|
||||
elif req.action == 'flee':
|
||||
# 50% chance to flee from PvP
|
||||
if random.random() < 0.5:
|
||||
result_message = f"You successfully fled from {opponent['name']}!"
|
||||
last_action_text = f"{current_player['name']} fled from combat!"
|
||||
messages.append(create_combat_message(
|
||||
"flee_success",
|
||||
origin="player"
|
||||
))
|
||||
|
||||
combat_over = True
|
||||
|
||||
# Mark as fled, store last action with timestamp, and end combat
|
||||
flee_field = 'attacker_fled' if is_attacker else 'defender_fled'
|
||||
await db.update_pvp_combat(pvp_combat['id'], {
|
||||
flee_field: True,
|
||||
'last_action': f"{current_player['name']} fled from combat!|{time.time()}"
|
||||
'last_action': f"{last_action_text}|{time.time()}"
|
||||
})
|
||||
await db.end_pvp_combat(pvp_combat['id'])
|
||||
await db.update_player_statistics(current_player['id'],
|
||||
@@ -979,11 +1069,17 @@ async def pvp_combat_action(
|
||||
)
|
||||
else:
|
||||
# Failed to flee, skip turn
|
||||
result_message = f"Failed to flee from {opponent['name']}!"
|
||||
last_action_text = f"{current_player['name']} tried to flee but failed!"
|
||||
messages.append(create_combat_message(
|
||||
"flee_fail",
|
||||
origin="player",
|
||||
reason="chance"
|
||||
))
|
||||
|
||||
await db.update_pvp_combat(pvp_combat['id'], {
|
||||
'turn': 'defender' if is_attacker else 'attacker',
|
||||
'turn_started_at': time.time(),
|
||||
'last_action': f"{current_player['name']} tried to flee but failed!|{time.time()}"
|
||||
'last_action': f"{last_action_text}|{time.time()}"
|
||||
})
|
||||
await db.update_player_statistics(current_player['id'],
|
||||
pvp_failed_flees=1,
|
||||
@@ -1041,20 +1137,22 @@ async def pvp_combat_action(
|
||||
await manager.send_personal_message(player_id, {
|
||||
"type": "combat_update",
|
||||
"data": {
|
||||
"message": result_message if player_id == current_user['id'] else "",
|
||||
"log_entry": result_message if player_id == current_user['id'] else "", # Append to combat log
|
||||
"message": last_action_text if player_id == current_user['id'] else "",
|
||||
"log_entry": last_action_text if player_id == current_user['id'] else "", # Append to combat log
|
||||
"pvp_combat": enriched_pvp,
|
||||
"combat_over": combat_over,
|
||||
"winner_id": winner_id,
|
||||
"attacker_hp": fresh_attacker['hp'],
|
||||
"defender_hp": fresh_defender['hp']
|
||||
"defender_hp": fresh_defender['hp'],
|
||||
"messages": messages if player_id == current_user['id'] else []
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
})
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": result_message,
|
||||
"messages": messages,
|
||||
"combat_over": combat_over,
|
||||
"winner_id": winner_id
|
||||
"winner_id": winner_id,
|
||||
"pvp_combat": updated_pvp
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
Equipment router.
|
||||
Auto-generated from main.py migration.
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from fastapi import APIRouter, HTTPException, Depends, status, Request
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
@@ -12,7 +12,7 @@ import logging
|
||||
|
||||
from ..core.security import get_current_user, security, verify_internal_key
|
||||
from ..services.models import *
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, calculate_crafting_stamina_cost
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, calculate_crafting_stamina_cost, get_game_message, get_locale_string
|
||||
from .. import database as db
|
||||
from ..items import ItemsManager
|
||||
from .. import game_logic
|
||||
@@ -41,10 +41,12 @@ router = APIRouter(tags=["equipment"])
|
||||
@router.post("/api/game/equip")
|
||||
async def equip_item(
|
||||
equip_req: EquipItemRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Equip an item from inventory"""
|
||||
player_id = current_user['id']
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get the inventory item
|
||||
inv_item = await db.get_inventory_item_by_id(equip_req.inventory_id)
|
||||
@@ -107,9 +109,9 @@ async def equip_item(
|
||||
|
||||
# Build message
|
||||
if unequipped_item_name:
|
||||
message = f"Unequipped {unequipped_item_name}, equipped {item_def.name}"
|
||||
message = get_game_message('unequip_equip', locale, old=unequipped_item_name, new=get_locale_string(item_def.name, locale))
|
||||
else:
|
||||
message = f"Equipped {item_def.name}"
|
||||
message = get_game_message('equipped', locale, item=get_locale_string(item_def.name, locale))
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
@@ -122,10 +124,12 @@ async def equip_item(
|
||||
@router.post("/api/game/unequip")
|
||||
async def unequip_item(
|
||||
unequip_req: UnequipItemRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Unequip an item from equipment slot"""
|
||||
player_id = current_user['id']
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Check if slot is valid
|
||||
valid_slots = ['head', 'torso', 'legs', 'feet', 'weapon', 'offhand', 'backpack']
|
||||
@@ -190,7 +194,7 @@ async def unequip_item(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Unequipped {item_def.name} (dropped to ground - inventory full)",
|
||||
"message": get_game_message('unequip_dropped', locale, item=get_locale_string(item_def.name, locale)),
|
||||
"dropped": True
|
||||
}
|
||||
|
||||
@@ -200,7 +204,7 @@ async def unequip_item(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Unequipped {item_def.name}",
|
||||
"message": get_game_message('unequipped', locale, item=get_locale_string(item_def.name, locale)),
|
||||
"dropped": False
|
||||
}
|
||||
|
||||
@@ -241,10 +245,12 @@ async def get_equipment(current_user: dict = Depends(get_current_user)):
|
||||
@router.post("/api/game/repair_item")
|
||||
async def repair_item(
|
||||
repair_req: RepairItemRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Repair an item using materials at a workbench location"""
|
||||
player_id = current_user['id']
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get player's location
|
||||
player = await db.get_player_by_id(player_id)
|
||||
@@ -358,7 +364,7 @@ async def repair_item(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Repaired {item_def.name}! Restored {repair_amount} durability.",
|
||||
"message": get_game_message('repaired_success', locale, item=get_locale_string(item_def.name, locale), amount=repair_amount),
|
||||
"item_name": item_def.name,
|
||||
"old_durability": current_durability,
|
||||
"new_durability": new_durability,
|
||||
|
||||
@@ -12,7 +12,7 @@ import logging
|
||||
|
||||
from ..core.security import get_current_user, security, verify_internal_key
|
||||
from ..services.models import *
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, get_locale_string
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, get_locale_string, get_game_message
|
||||
from .. import database as db
|
||||
from ..items import ItemsManager
|
||||
from .. import game_logic
|
||||
@@ -757,7 +757,7 @@ async def move(
|
||||
if cooldown_remaining > 0:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"You must wait {int(cooldown_remaining)} seconds before moving again."
|
||||
detail=get_game_message('move_cooldown', locale, seconds=int(cooldown_remaining))
|
||||
)
|
||||
|
||||
# Extract locale from Accept-Language header
|
||||
@@ -870,7 +870,7 @@ async def move(
|
||||
response["encounter"] = {
|
||||
"triggered": True,
|
||||
"enemy_id": enemy_id,
|
||||
"message": f"⚠️ An enemy ambushes you upon arrival!",
|
||||
"message": get_game_message('enemy_ambush', locale),
|
||||
"combat": combat_data
|
||||
}
|
||||
|
||||
@@ -881,7 +881,7 @@ async def move(
|
||||
{
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} left the area",
|
||||
"message": get_game_message('player_left', locale, player_name=player['name']),
|
||||
"action": "player_left",
|
||||
"player_id": current_user['id'],
|
||||
"player_name": player['name']
|
||||
@@ -897,7 +897,7 @@ async def move(
|
||||
{
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} arrived",
|
||||
"message": get_game_message('player_arrived', locale, player_name=player['name']),
|
||||
"action": "player_arrived",
|
||||
"player_id": current_user['id'],
|
||||
"player_name": player['name'],
|
||||
@@ -930,8 +930,11 @@ async def move(
|
||||
|
||||
|
||||
@router.post("/api/game/inspect")
|
||||
async def inspect(current_user: dict = Depends(get_current_user)):
|
||||
async def inspect(request: Request, current_user: dict = Depends(get_current_user)):
|
||||
"""Inspect the current area"""
|
||||
# Extract locale from Accept-Language header
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
location_id = current_user['location_id']
|
||||
location = LOCATIONS.get(location_id)
|
||||
|
||||
@@ -947,7 +950,8 @@ async def inspect(current_user: dict = Depends(get_current_user)):
|
||||
message = await game_logic.inspect_area(
|
||||
current_user['id'],
|
||||
location,
|
||||
{} # interactables_data - not needed with new structure
|
||||
{}, # interactables_data - not needed with new structure
|
||||
locale
|
||||
)
|
||||
|
||||
return {
|
||||
@@ -971,7 +975,7 @@ async def interact(
|
||||
if combat:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Cannot interact with objects while in combat"
|
||||
detail=get_game_message('interact_in_combat', locale)
|
||||
)
|
||||
|
||||
location_id = current_user['location_id']
|
||||
@@ -988,7 +992,8 @@ async def interact(
|
||||
interact_req.interactable_id,
|
||||
interact_req.action_id,
|
||||
location,
|
||||
ITEMS_MANAGER
|
||||
ITEMS_MANAGER,
|
||||
locale
|
||||
)
|
||||
|
||||
if not result['success']:
|
||||
@@ -1052,6 +1057,7 @@ async def interact(
|
||||
@router.post("/api/game/use_item")
|
||||
async def use_item(
|
||||
use_req: UseItemRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Use an item from inventory"""
|
||||
@@ -1064,10 +1070,14 @@ async def use_item(
|
||||
combat = await db.get_active_combat(current_user['id'])
|
||||
in_combat = combat is not None
|
||||
|
||||
# Extract locale from Accept-Language header
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
result = await game_logic.use_item(
|
||||
current_user['id'],
|
||||
use_req.item_id,
|
||||
ITEMS_MANAGER
|
||||
ITEMS_MANAGER,
|
||||
locale
|
||||
)
|
||||
|
||||
if not result['success']:
|
||||
@@ -1087,10 +1097,10 @@ async def use_item(
|
||||
npc_damage = int(npc_damage * 1.5)
|
||||
|
||||
new_player_hp = max(0, player['hp'] - npc_damage)
|
||||
combat_message = f"\n{npc_def.name} attacks for {npc_damage} damage!"
|
||||
combat_message = get_game_message('combat_enemy_attack', locale, name=npc_def.name, damage=npc_damage)
|
||||
|
||||
if new_player_hp <= 0:
|
||||
combat_message += "\nYou have been defeated!"
|
||||
combat_message += get_game_message('combat_defeated', locale)
|
||||
await db.update_player(current_user['id'], hp=0, is_dead=True)
|
||||
await db.end_combat(current_user['id'])
|
||||
result['combat_over'] = True
|
||||
@@ -1149,7 +1159,7 @@ async def use_item(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} was defeated in combat",
|
||||
"message": get_game_message('player_defeated_broadcast', locale, player_name=player['name']),
|
||||
"action": "player_died",
|
||||
"player_id": player['id'],
|
||||
"corpse": corpse_data # Send full corpse data
|
||||
@@ -1194,7 +1204,8 @@ async def pickup(
|
||||
pickup_req.item_id,
|
||||
current_user['location_id'],
|
||||
pickup_req.quantity,
|
||||
ITEMS_MANAGER
|
||||
ITEMS_MANAGER,
|
||||
locale
|
||||
)
|
||||
|
||||
if not result['success']:
|
||||
@@ -1214,7 +1225,7 @@ async def pickup(
|
||||
{
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} picked up {quantity}x {item_name}",
|
||||
"message": f"{player['name']} {get_game_message('picked_up', locale).lower()} {quantity}x {item_name}",
|
||||
"action": "item_picked_up"
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
@@ -1336,6 +1347,7 @@ async def get_inventory(current_user: dict = Depends(get_current_user)):
|
||||
@router.post("/api/game/item/drop")
|
||||
async def drop_item(
|
||||
drop_req: dict,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Drop an item from inventory"""
|
||||
@@ -1343,6 +1355,9 @@ async def drop_item(
|
||||
item_id = drop_req.get('item_id') # This is the item_id string like "energy_bar"
|
||||
quantity = drop_req.get('quantity', 1)
|
||||
|
||||
# Extract locale from Accept-Language header
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Get player to know their location
|
||||
player = await db.get_player_by_id(player_id)
|
||||
if not player:
|
||||
@@ -1400,7 +1415,7 @@ async def drop_item(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} dropped {item_def.emoji} {item_def.name} x{quantity}",
|
||||
"message": get_game_message('dropped_item_success', locale, emoji=item_def.emoji, name=get_locale_string(item_def.name, locale), qty=quantity).replace('You', player['name']).replace('Has tirado', f"{player['name']} ha tirado"),
|
||||
"action": "item_dropped"
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
@@ -1410,5 +1425,5 @@ async def drop_item(
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Dropped {item_def.emoji} {get_locale_string(item_def.name)} x{quantity}"
|
||||
"message": get_game_message('dropped_item_success', locale, emoji=item_def.emoji, name=get_locale_string(item_def.name, locale), qty=quantity)
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
Loot router.
|
||||
Auto-generated from main.py migration.
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Depends, status
|
||||
from fastapi import APIRouter, HTTPException, Depends, status, Request
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
from typing import Optional, Dict, Any
|
||||
from datetime import datetime
|
||||
@@ -12,7 +12,7 @@ import logging
|
||||
|
||||
from ..core.security import get_current_user, security, verify_internal_key
|
||||
from ..services.models import *
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, get_locale_string
|
||||
from ..services.helpers import calculate_distance, calculate_stamina_cost, calculate_player_capacity, get_locale_string, get_game_message
|
||||
from .. import database as db
|
||||
from ..items import ItemsManager
|
||||
from .. import game_logic
|
||||
@@ -42,6 +42,7 @@ router = APIRouter(tags=["loot"])
|
||||
@router.get("/api/game/corpse/{corpse_id}")
|
||||
async def get_corpse_details(
|
||||
corpse_id: str,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Get detailed information about a corpse's lootable items"""
|
||||
@@ -50,6 +51,9 @@ async def get_corpse_details(
|
||||
sys.path.insert(0, '/app')
|
||||
from data.npcs import NPCS
|
||||
|
||||
# Extract locale
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Parse corpse ID
|
||||
corpse_type, corpse_db_id = corpse_id.split('_', 1)
|
||||
corpse_db_id = int(corpse_db_id)
|
||||
@@ -99,7 +103,7 @@ async def get_corpse_details(
|
||||
return {
|
||||
'corpse_id': corpse_id,
|
||||
'type': 'npc',
|
||||
'name': f"{npc_def.name if npc_def else corpse['npc_id']} Corpse",
|
||||
'name': get_game_message('corpse_name_npc', locale, name=get_locale_string(npc_def.name, locale) if npc_def else corpse['npc_id']),
|
||||
'loot_items': loot_items,
|
||||
'total_items': len(loot_items)
|
||||
}
|
||||
@@ -137,7 +141,7 @@ async def get_corpse_details(
|
||||
return {
|
||||
'corpse_id': corpse_id,
|
||||
'type': 'player',
|
||||
'name': f"{corpse['player_name']}'s Corpse",
|
||||
'name': get_game_message('corpse_name_player', locale, name=corpse['player_name']),
|
||||
'loot_items': loot_items,
|
||||
'total_items': len(loot_items)
|
||||
}
|
||||
@@ -149,6 +153,7 @@ async def get_corpse_details(
|
||||
@router.post("/api/game/loot_corpse")
|
||||
async def loot_corpse(
|
||||
req: LootCorpseRequest,
|
||||
request: Request,
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""Loot a corpse (NPC or player) - can loot specific item by index or all items"""
|
||||
@@ -158,6 +163,9 @@ async def loot_corpse(
|
||||
sys.path.insert(0, '/app')
|
||||
from data.npcs import NPCS
|
||||
|
||||
# Extract locale
|
||||
locale = request.headers.get('Accept-Language', 'en')
|
||||
|
||||
# Parse corpse ID
|
||||
corpse_type, corpse_db_id = req.corpse_id.split('_', 1)
|
||||
corpse_db_id = int(corpse_db_id)
|
||||
@@ -310,26 +318,26 @@ async def loot_corpse(
|
||||
message_parts = []
|
||||
for item in looted_items:
|
||||
item_def = ITEMS_MANAGER.get_item(item['item_id'])
|
||||
item_name = get_locale_string(item_def.name) if item_def else item['item_id']
|
||||
item_name = get_locale_string(item_def.name, locale) if item_def else item['item_id']
|
||||
message_parts.append(f"{item_def.emoji if item_def else ''} {item_name} x{item['quantity']}")
|
||||
|
||||
dropped_parts = []
|
||||
for item in dropped_items:
|
||||
item_def = ITEMS_MANAGER.get_item(item['item_id'])
|
||||
item_name = get_locale_string(item_def.name) if item_def else item['item_id']
|
||||
item_name = get_locale_string(item_def.name, locale) if item_def else item['item_id']
|
||||
dropped_parts.append(f"{item.get('emoji', '📦')} {item_name} x{item['quantity']}")
|
||||
|
||||
message = ""
|
||||
if message_parts:
|
||||
message = "Looted: " + ", ".join(message_parts)
|
||||
message = get_game_message('looted_items_start', locale) + ", ".join(message_parts)
|
||||
if dropped_parts:
|
||||
if message:
|
||||
message += "\n"
|
||||
message += "⚠️ Backpack full! Dropped on ground: " + ", ".join(dropped_parts)
|
||||
message += get_game_message('backpack_full_drop', locale) + ", ".join(dropped_parts)
|
||||
if not message_parts and not dropped_parts:
|
||||
message = "Nothing could be looted"
|
||||
message = get_game_message('nothing_looted', locale)
|
||||
if remaining_loot and req.item_index is None:
|
||||
message += f"\n{len(remaining_loot)} item(s) require tools to extract"
|
||||
message += "\n" + get_game_message('items_require_tools', locale, count=len(remaining_loot))
|
||||
|
||||
# Broadcast to location about corpse looting
|
||||
if len(remaining_loot) == 0:
|
||||
@@ -339,7 +347,7 @@ async def loot_corpse(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} fully looted an NPC corpse",
|
||||
"message": get_game_message('full_loot_broadcast', locale, player_name=player['name']),
|
||||
"action": "corpse_looted"
|
||||
},
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
@@ -438,24 +446,24 @@ async def loot_corpse(
|
||||
message_parts = []
|
||||
for item in looted_items:
|
||||
item_def = ITEMS_MANAGER.get_item(item['item_id'])
|
||||
item_name = get_locale_string(item_def.name) if item_def else item['item_id']
|
||||
item_name = get_locale_string(item_def.name, locale) if item_def else item['item_id']
|
||||
message_parts.append(f"{item_def.emoji if item_def else ''} {item_name} x{item['quantity']}")
|
||||
|
||||
dropped_parts = []
|
||||
for item in dropped_items:
|
||||
item_def = ITEMS_MANAGER.get_item(item['item_id'])
|
||||
item_name = get_locale_string(item_def.name) if item_def else item['item_id']
|
||||
item_name = get_locale_string(item_def.name, locale) if item_def else item['item_id']
|
||||
dropped_parts.append(f"{item.get('emoji', '📦')} {item_name} x{item['quantity']}")
|
||||
|
||||
message = ""
|
||||
if message_parts:
|
||||
message = "Looted: " + ", ".join(message_parts)
|
||||
message = get_game_message('looted_items_start', locale) + ", ".join(message_parts)
|
||||
if dropped_parts:
|
||||
if message:
|
||||
message += "\n"
|
||||
message += "⚠️ Backpack full! Dropped on ground: " + ", ".join(dropped_parts)
|
||||
message += get_game_message('backpack_full_drop', locale) + ", ".join(dropped_parts)
|
||||
if not message_parts and not dropped_parts:
|
||||
message = "Nothing could be looted"
|
||||
message = get_game_message('nothing_looted', locale)
|
||||
|
||||
# Broadcast to location about corpse looting
|
||||
if len(remaining_items) == 0:
|
||||
@@ -465,7 +473,7 @@ async def loot_corpse(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} fully looted {corpse['player_name']}'s corpse",
|
||||
"message": get_game_message('player_corpse_emptied_broadcast', locale, player_name=player['name'], corpse_name=corpse['player_name']),
|
||||
"action": "player_corpse_emptied",
|
||||
"corpse_id": req.corpse_id
|
||||
},
|
||||
@@ -480,7 +488,7 @@ async def loot_corpse(
|
||||
message={
|
||||
"type": "location_update",
|
||||
"data": {
|
||||
"message": f"{player['name']} looted from {corpse['player_name']}'s corpse",
|
||||
"message": get_game_message('player_corpse_looted_broadcast', locale, player_name=player['name'], corpse_name=corpse['player_name']),
|
||||
"action": "player_corpse_looted",
|
||||
"corpse_id": req.corpse_id,
|
||||
"remaining_items": remaining_items,
|
||||
|
||||
Reference in New Issue
Block a user