Files
echoes-of-the-ash/docs/PICKUP_AND_CORPSE_ENHANCEMENTS.md
2025-11-07 15:27:13 +01:00

9.9 KiB

Pickup and Corpse Looting Enhancements

Date: November 5, 2025

Issues Fixed

1. Pickup Error 500 Fixed

Problem: When trying to pick up items from the ground, the game threw a 500 error.

Root Cause: The game_logic.pickup_item() function was importing from the old data.items.ITEMS dictionary instead of using the new ItemsManager class. The old ITEMS returns dicts, not objects with attributes, causing AttributeError: 'dict' object has no attribute 'weight'.

Solution:

  • Modified api/game_logic.py - pickup_item() function now accepts items_manager as a parameter
  • Updated api/main.py - pickup endpoint now passes ITEMS_MANAGER to game_logic.pickup_item()
  • Removed import of old data.items.ITEMS module

Files Changed:

  • api/game_logic.py (lines 305-346)
  • api/main.py (line 876)

2. Enhanced Corpse Looting System

Problem: Corpse looting was all-or-nothing. Players couldn't see what items were available, which ones required tools, or loot items individually.

Solution: Implemented a comprehensive corpse inspection and individual item looting system.

Backend Changes

New Endpoint: GET /api/game/corpse/{corpse_id}

  • Returns detailed information about a corpse's lootable items
  • Shows each item with:
    • Item name, emoji, and quantity range
    • Required tool (if any)
    • Whether player has the required tool
    • Whether item can be looted
  • Works for both NPC and player corpses

Updated Endpoint: POST /api/game/loot_corpse

  • Now accepts optional item_index parameter
  • If item_index is provided: loots only that specific item
  • If item_index is null: loots all items player has tools for (original behavior)
  • Returns remaining_count to show how many items are left
  • Validates tool requirements before looting

Models Updated:

class LootCorpseRequest(BaseModel):
    corpse_id: str
    item_index: Optional[int] = None  # New field

Frontend Changes

New State Variables:

const [expandedCorpse, setExpandedCorpse] = useState<string | null>(null)
const [corpseDetails, setCorpseDetails] = useState<any>(null)

New Handler Functions:

  • handleViewCorpseDetails() - Fetches and displays corpse contents
  • handleLootCorpseItem() - Loots individual items or all available items
  • Modified handleLootCorpse() - Now opens detailed view instead of looting immediately

UI Enhancements:

  • Corpse card now shows "🔍 Examine" button instead of "🔍 Loot"
  • Clicking Examine expands corpse to show all lootable items
  • Each item shows:
    • Item emoji, name, and quantity range
    • Tool requirement with ✓ (has tool) or ✗ (needs tool) indicator
    • Color-coded tool status (green = has, red = needs)
    • Individual "📦 Loot" button per item
    • Disabled/locked state for items requiring tools
  • "📦 Loot All Available" button at bottom
  • Close button (✕) to collapse corpse details
  • Smooth slide-down animation when expanding

CSS Styling Added:

  • .corpse-card - Purple-themed corpse cards matching danger level 5 color
  • .corpse-container - Flexbox wrapper for card + details
  • .corpse-details - Expansion panel with slide-down animation
  • .corpse-details-header - Header with title and close button
  • .corpse-items-list - List container for loot items
  • .corpse-item - Individual loot item card
  • .corpse-item.locked - Reduced opacity for items requiring tools
  • .corpse-item-tool.has-tool - Green indicator for available tools
  • .corpse-item-tool.needs-tool - Red indicator for missing tools
  • .corpse-item-loot-btn - Individual loot button (green gradient)
  • .loot-all-btn - Loot all button (purple gradient)

Files Changed:

  • api/main.py (lines 893-1189) - New endpoint and updated loot logic
  • pwa/src/components/Game.tsx (lines 72-73, 276-312, 755-828) - State, handlers, and UI
  • pwa/src/components/Game.css (lines 723-919) - Extensive corpse detail styling

User Experience Improvements

Before:

  1. Click "Loot" on corpse
  2. Automatically loot all items (if have tools) or get error message
  3. No visibility into what items are available
  4. No way to choose which items to take

After:

  1. Click "🔍 Examine" on corpse
  2. See detailed list of all lootable items
  3. Each item shows:
    • What it is (emoji + name)
    • How many you might get (quantity range)
    • If it requires a tool (and whether you have it)
  4. Choose to loot items individually OR loot all at once
  5. Items requiring tools show clear indicators
  6. Can close and come back later for items you don't have tools for yet

Technical Benefits

  1. Better Error Handling - Clear feedback about missing tools
  2. Granular Control - Players can pick and choose what to loot
  3. Tool Visibility - Players know exactly what tools they need
  4. Inventory Management - Can avoid picking up unwanted items
  5. Persistent State - Corpses remain with items until fully looted
  6. Better UX - Smooth animations and clear visual feedback

Testing Checklist

  • Pickup items from ground works without errors
  • Corpse examination shows all items correctly
  • Tool requirements display correctly
  • Individual item looting works
  • "Loot All" button works
  • Items requiring tools can't be looted without tools
  • Corpse details refresh after looting individual items
  • Corpse disappears when fully looted
  • Error messages are clear and helpful
  • UI animations work smoothly
  • Both NPC and player corpses work correctly

Additional Fixes (Second Iteration)

Issue 1: Messages Disappearing Too Quickly

Problem: Loot success messages were disappearing almost immediately, making it hard to see what was looted.

Solution:

  • Removed the "Examining corpse..." message that was flickering
  • Added 5-second timer for loot messages to stay visible
  • Messages now persist long enough to read

Issue 2: Weight/Volume Validation Not Working

Problem: Players could pick up items even when over weight/volume limits.

Solution:

  • Added calculate_player_capacity() helper function in api/main.py
  • Updated pickup_item() in api/game_logic.py to properly calculate capacity
  • Calculates current weight, max weight, current volume, max volume
  • Accounts for equipped bags/containers that increase capacity
  • Applied to both pickup and corpse looting
  • Better error messages showing current capacity vs. item requirements

Issue 3: Items Lost When Inventory Full

Problem: When looting corpses with full inventory, items would disappear instead of being left behind.

Solution:

  • Items that don't fit are now dropped on the ground at player's location
  • Loot message shows two sections:
    • "Looted: " - items successfully added to inventory
    • "⚠️ Backpack full! Dropped on ground: " - items dropped
  • Items remain in the world for later pickup
  • Corpse is cleared of the item (preventing duplication)

Backend Changes

New Helper Function:

async def calculate_player_capacity(player_id: int):
    """Calculate player's current and max weight/volume capacity"""
    # Returns: (current_weight, max_weight, current_volume, max_volume)

Updated loot_corpse Endpoint:

  • Calculates player capacity before looting
  • Checks each item against weight/volume limits
  • If item fits: adds to inventory, updates running weight/volume
  • If item doesn't fit: drops on ground at player location
  • Works for both NPC and player corpses
  • Works for both individual items and "loot all"

Response Format Updated:

{
    "success": True,
    "message": "Looted: 🥩 Meat x3\n⚠️ Backpack full! Dropped on ground: 🔫 Rifle x1",
    "looted_items": [...],
    "dropped_items": [...],  # NEW
    "corpse_empty": True,
    "remaining_count": 0
}

Frontend Changes

Updated handleViewCorpseDetails():

  • Removed "Examining corpse..." message to prevent flicker
  • Directly opens corpse details without transitional message

Updated handleLootCorpseItem():

  • Keeps message visible longer (5 seconds)
  • Refreshes corpse details without clearing loot message
  • Better async handling for corpse refresh

Files Changed:

  • api/main.py (lines 45-70, 1035-1246)
  • api/game_logic.py (lines 305-385) - Fixed pickup validation
  • pwa/src/components/Game.tsx (lines 276-323)

Deployment

Both API and PWA containers have been rebuilt and deployed successfully.

Deployment Command:

docker compose build echoes_of_the_ashes_api echoes_of_the_ashes_pwa
docker compose up -d echoes_of_the_ashes_api echoes_of_the_ashes_pwa

Status: All services running successfully

Deployment Date: November 5, 2025 (Second iteration)

Third Iteration - Pickup Validation Fix

Issue: Pickup from Ground Not Validating Weight/Volume

Problem: While corpse looting correctly validated weight/volume and dropped items that didn't fit, picking up items from the ground bypassed these checks entirely.

Root Cause: The pickup_item() function in game_logic.py had weight/volume validation code, but it was using:

  • Hardcoded max_volume = 30
  • player.get('max_weight', 50) which didn't account for equipped bags
  • Didn't calculate equipped bag bonuses properly

Solution: Updated pickup_item() function to match the corpse looting logic:

  • Properly calculate base capacity (10kg/10L)
  • Loop through inventory to check for equipped bags
  • Add bag capacity bonuses from item_def.stats.get('weight_capacity', 0)
  • Validate BEFORE removing item from ground
  • Better error messages with emoji and current capacity info

Example Error Messages:

⚠️ Item too heavy! 🔫 Rifle x1 (5.0kg) would exceed capacity. Current: 8.5/10.0kg
⚠️ Item too large! 📦 Large Box x1 (15.0L) would exceed capacity. Current: 7.0/10.0L

Success Message Updated:

Picked up 🥩 Meat x3

Files Changed:

  • api/game_logic.py (lines 305-385) - Complete rewrite of capacity calculation

Status: Deployed and validated (saw 400 error in logs = validation working)

Deployment Date: November 5, 2025 (Third iteration)