# Salvage UI & Armor Durability Updates **Date:** 2025-11-07 ## Summary Fixed salvage UI to show item details and durability-based yield, plus implemented armor durability reduction in combat. ## Changes Implemented ### 1. Salvage Item Details Display ✅ **Files:** `pwa/src/components/Game.tsx` **Issue:** Salvage menu was not showing which specific item you're salvaging (e.g., which knife when you have multiple). **Solution:** - Updated frontend to call `/api/game/salvageable` endpoint instead of filtering inventory - Now displays for each salvageable item: - Current/max durability and percentage - Tier level - Unique stats (damage, armor, etc.) - Expected material yield adjusted for durability **Example Display:** ``` 🔪 Knife (Tier 2) 🔧 Durability: 30/100 (30%) damage: 15 ⚠️ Item condition will reduce yield by 70% ⚠️ 30% chance to lose each material ♻️ Expected yield: 🔩 Metal Scrap x4 → x1 📦 Cloth x2 → x0 * Subject to 30% random loss per material ``` ### 2. Durability-Based Yield Preview ✅ **Files:** `pwa/src/components/Game.tsx` **Issue:** Salvage menu showed full material yield even when item had low durability. **Solution:** - Calculate `durability_ratio = durability_percent / 100` - Show adjusted yield: `adjusted_quantity = base_quantity * durability_ratio` - Cross out original quantity and show reduced amount in orange - Show warning if durability < 10% (yields nothing) **Visual Indicators:** - Normal durability (100%): `x4` - Reduced durability (30%): `~~x4~~ → x1` (strikethrough and arrow) - Too damaged (<10%): `x0` (in red) ### 3. Armor Durability Reduction in Combat ✅ **Files:** `api/main.py` **Feature:** Equipped armor now loses durability when you take damage in combat. **Function Added:** `reduce_armor_durability(player_id, damage_taken)` **Formula:** ```python # Calculate damage absorbed by armor (up to half the damage) armor_absorbed = min(damage_taken // 2, total_armor) # For each armor piece: proportion = armor_value / total_armor durability_loss = max(1, int((damage_taken * proportion / armor_value) * 0.5 * 10)) ``` **How It Works:** 1. **Armor absorbs damage** - Up to half the incoming damage is blocked by armor 2. **Durability reduction** - Each armor piece loses durability proportional to damage taken 3. **Higher armor = less durability loss** - Better armor pieces are more durable 4. **Armor breaks** - When durability reaches 0, the piece breaks and is removed **Combat Message Example:** ``` Zombie attacks for 20 damage! (Armor absorbed 8 damage) 💔 Your 🛡️ Leather Vest broke! ``` **Balance:** - Wearing full armor set (head, chest, legs, feet) can absorb significant damage - Base reduction rate: 0.5 (configurable) - Higher tier armor has more max durability and higher armor value - Encourages repairing armor between fights ## Technical Implementation ### Frontend Changes (Game.tsx) **1. Fetch salvageable items:** ```typescript const salvageableRes = await api.get('/api/game/salvageable') setUncraftableItems(salvageableRes.data.salvageable_items) ``` **2. Calculate adjusted yield:** ```typescript const durabilityRatio = item.unique_item_data ? item.unique_item_data.durability_percent / 100 : 1.0 const adjustedYield = item.base_yield.map((mat: any) => ({ ...mat, adjusted_quantity: Math.floor(mat.quantity * durability_ratio) })) ``` **3. Display unique item stats:** ```tsx {item.unique_item_data && (

🔧 Durability: {current}/{max} ({percent}%)

{Object.entries(unique_stats).map(([stat, value]) => ( {stat}: {value} ))}
)} ``` ### Backend Changes (api/main.py) **1. Armor durability reduction function:** ```python async def reduce_armor_durability(player_id: int, damage_taken: int): """Reduce durability of equipped armor when taking damage""" # Collect all equipped armor pieces # Calculate total armor value # Determine damage absorbed # Reduce durability proportionally per piece # Break and remove pieces with 0 durability return armor_absorbed, broken_armor ``` **2. Called during NPC attack:** ```python armor_absorbed, broken_armor = await reduce_armor_durability(player['id'], npc_damage) actual_damage = max(1, npc_damage - armor_absorbed) new_player_hp = max(0, player['hp'] - actual_damage) # Report absorbed damage and broken armor ``` ## Configuration **Armor Durability Formula Constants:** - `base_reduction_rate = 0.5` - Base multiplier for durability loss - `armor_absorption = damage // 2` - Armor blocks up to 50% of damage - `min_damage = 1` - Always take at least 1 damage even with high armor To adjust armor durability loss, modify `base_reduction_rate` in `reduce_armor_durability()` function. ## Benefits 1. **Informed Salvage Decisions** - See which specific item you're salvaging 2. **Realistic Yield** - Damaged items yield fewer materials 3. **Armor Wear** - Armor degrades realistically, encouraging maintenance 4. **Combat Strategy** - Need to repair/replace armor regularly 5. **Resource Management** - Can't salvage broken items for full materials ## Testing **Salvage UI:** - ✅ Shows unique item details - ✅ Shows adjusted yield based on durability - ✅ Shows warning for low durability items - ✅ Confirmation dialog shows expected yield **Armor Durability:** - ✅ Armor absorbs damage (up to 50%) - ✅ Armor loses durability when hit - ✅ Armor breaks at 0 durability - ✅ Broken armor message displayed - ✅ Player takes reduced damage with armor ## Future Enhancements 1. **Armor Repair** - Add repair functionality for armor pieces 2. **Armor Sets** - Bonus for wearing complete armor sets 3. **Armor Tiers** - Higher tier armor is more durable 4. **Repair Kits** - Special items to repair armor in the field 5. **Armor Degradation Visual** - Show armor condition in equipment UI ## Files Modified - `pwa/src/components/Game.tsx` - Salvage UI updates - `api/main.py` - Armor durability reduction logic - `api/main.py` - Combat attack function updated ## Status ✅ **DEPLOYED** - All features tested and running in production