# Loot Screen Design

## Overview

The Loot Phase occurs after combat victory. Players claim new equipment, then manage their inventory by scrapping items for upgrade points or spending points to upgrade equipment. The screen reuses the combat layout's spatial metaphor, repurposing the battle area as an upgrade workspace.

---

## Layout Structure

### **Top Section: Workspace Area**
*(Formerly robot battle line - now the upgrade/loot management area)*

The top section has three states:

#### State 1: New Loot Display (Initial)
- Heading: "LOOT ACQUIRED!" or "SPOILS OF WAR!"
- Display newly acquired items as cards (floating where robots were)
- Visual effects: glowing, animated entry
- Auto-add to inventory or "Claim All" button
- Prominent upgrade points counter

#### State 2: Equipment Detail View (When item selected)
When player clicks equipment from tableau below:

**Left Side: Current State**
- Full card display at current upgrade level
- All current stats clearly shown

**Center: Upgrade Arrow/Connector**
- Visual arrow or connector showing progression
- Shows cost: "1 Upgrade Point"

**Right Side: Next Upgrade Preview**
- Shows what the item becomes at next level
- Highlighted stat changes (green for improvements)
- If max level: "MAX LEVEL" badge/indicator

**Action Buttons (large, clear, below the cards):**
- **"SCRAP (+1 Upgrade Point)"** - Red/orange, destructive styling
- **"UPGRADE (Costs 1 Point)"** - Green/blue, constructive styling, disabled if insufficient points
- **"USE NOW"** - Yellow/cyan, only visible for health consumables
- Buttons should be large, distinct, and hard to misclick

**Always Visible:**
- Upgrade points counter (top-right or top-center)
- Item name and type
- Current upgrade level indicator (e.g., "Level 2/3")

#### State 3: Idle/Instructions (Nothing selected)
- Instructions: "Select equipment below to upgrade or scrap"
- Summary info (optional):
  - Total items in inventory
  - Upgrade points available
- **Continue Button**: "Continue" or "Take Elevator" (if unlocked)
  - Proceeds to next encounter or level

### **Bottom Section: Player Tableau**
*(Same layout as combat - equipment cards)*

**Layout:**
- Identical positioning to combat phase
- Same equipment cards in same locations
- Familiar spatial arrangement

**Interaction Mode:**
- Click to **select** (not to use/attack)
- Selected card gets highlight border or glow
- Click again to deselect, or click another to switch selection

**Visual Indicators on Cards:**
- ⬆️ **Upgrade Level**: Pips/dots showing current level (0-3)
- ✨ **Upgradeable**: Subtle glow/shimmer if player has points available
- 🆕 **New Item**: "NEW" badge for just-acquired loot
- 💚 **Usable**: Health icon for consumables that can be used
- 🔒 **Cannot Scrap**: Visual indicator for starting gear/charger

**Card Display:**
- Show compact stats (same as combat)
- Name, type, charges/damage
- Brief description

---

## User Flow

1. **Combat Victory** → Transition to loot phase
2. **Loot Display**: Top section shows new items acquired
3. **Claim Loot**: Items auto-add or player clicks "Claim All"
4. **Inspect**: Player clicks equipment in tableau → Details appear in workspace
5. **Decide**: Player chooses action via buttons in workspace:
   - **Scrap**: Item removed, +1 upgrade point
   - **Upgrade**: -1 upgrade point, item levels up
   - **Use**: For health consumables only
6. **Repeat**: Select another item and repeat, or...
7. **Continue**: Click "Continue" to proceed to next phase

---

## Visual Continuity & Polish

### Spatial Metaphor
- Maintain the "arena" concept from combat
- Top section = "workbench" or "upgrade table"
- Bottom section = "your gear" (same as combat)

### Animations & Transitions
- **Loot Acquired**: New cards fly in from off-screen
- **Claim Loot**: Cards animate down into tableau positions
- **Selection**: Selected card "projects" or "echoes" into workspace above
- **Scrap**: Card disintegrates/fades with particle effect
- **Upgrade**: Card "levels up" animation with stat changes highlighted
- **Use Consumable**: Brief effect, then card disappears

### Visual Hierarchy
- **Upgrade points counter**: Large, prominent, always visible
- **Action buttons**: Big, distinct colors, clear labels
- **Selected equipment**: Clear highlight/border
- **Upgrade preview**: Stat changes use color coding (green = better)

---

## Technical Notes

### Phase Configuration
```javascript
loot: {
  start: true, // For isolated testing
  next: 'combat', // Eventually cycles back to combat
  
  onBegin: ({ G, ctx }) => {
    // Initialize loot state
    // Clear selected equipment
    // Set available actions
  },
  
  moves: {
    selectEquipment: (equipmentId) => { /* ... */ },
    scrapEquipment: (equipmentId) => { /* ... */ },
    upgradeEquipment: (equipmentId) => { /* ... */ },
    useConsumable: (equipmentId) => { /* ... */ },
    continueToNextEncounter: () => { /* ... */ },
  }
}
```

### State Requirements
```javascript
G: {
  // ... existing state
  
  loot: {
    selectedEquipment: null, // Currently selected item ID
    newlyAcquired: [], // IDs of items just looted
  }
}
```

### Component Structure
- **`LootBoard.jsx`**: Main loot phase component
  - Reuses `EquipmentCard` components from combat
  - New: `UpgradeWorkspace` subcomponent for top section
  - New: `UpgradePreview` subcomponent for showing upgrade paths
  
### Equipment Card Reuse
- Same `EquipmentCard.jsx` component used in both phases
- Pass different handlers based on phase:
  - Combat: `onSelect` → select as weapon, `onUse` → use ability
  - Loot: `onSelect` → show in workspace, no `onUse`

---

## Implementation Details

### 1. Tableau Reuse Strategy

The key is that `EquipmentCard` already accepts a `handlers` prop with different callbacks. We'll render the same component with different interaction logic.

**Combat Phase** (`CombatBoard.jsx`):
```javascript
<EquipmentCard
  equipmentId={id}
  equipment={equipment}
  G={G}
  handlers={{
    onSelect: () => setSelectedWeapon(id),  // Mark as selected weapon
    onUse: () => moves.useEquipment(id),     // Use immediately
    disabled: !canAct
  }}
  isSelected={selectedWeapon === id}
/>
```

**Loot Phase** (`LootBoard.jsx`):
```javascript
<EquipmentCard
  equipmentId={id}
  equipment={equipment}
  G={G}
  handlers={{
    onSelect: () => setSelectedForUpgrade(id),  // Show in workspace above
    // No onUse handler - different interaction mode
    disabled: false
  }}
  isSelected={selectedForUpgrade === id}
/>
```

**Top Section Difference:**
- **Combat**: Robot battle line (separate component structure)
- **Loot**: Upgrade workspace (completely new component: `UpgradeWorkspace`)

The entire `LootBoard.jsx` is a separate component from `CombatBoard.jsx`, allowing complete UI customization while reusing the equipment card rendering logic.

### 2. Upgrade System: Data-Driven Preview

Upgrades are already defined in the card definitions:

```javascript
// weapons.js example
blaster: {
  // ... base properties
  upgrades: {
    level1: { maxCharges: 3, description: '+1 capacity' },
    level2: { maxCharges: 4, description: '+1 capacity' },
    level3: { damage: 2, description: '+1 dmg' },
  }
}
```

**Helper Function: Get Upgrade Preview**

Create `src/game/helpers/upgrades.js`:

```javascript
import { getEquipmentDefinition } from '../cards';

/**
 * Generate a preview of what the equipment will become at next level
 * @param {Object} equipment - Current equipment instance from G.player.equipment
 * @param {Object} equipmentDef - Equipment definition from cards (optional, will look up if not provided)
 * @returns {Object|null} - { preview, changes, description, level } or null if max level
 */
export function getUpgradePreview(equipment, equipmentDef = null) {
  if (!equipmentDef) {
    equipmentDef = getEquipmentDefinition(equipment.id);
  }
  
  const nextLevel = equipment.upgradeLevel + 1;
  const upgrade = equipmentDef.upgrades?.[`level${nextLevel}`];
  
  // No more upgrades available
  if (!upgrade || nextLevel > 3) {
    return null;
  }
  
  // Create preview by merging current state + upgrade changes
  const previewEquipment = { ...equipment };
  const changedProperties = [];
  
  Object.keys(upgrade).forEach(key => {
    if (key !== 'description') {
      changedProperties.push(key);
      previewEquipment[key] = upgrade[key];
    }
  });
  
  return {
    preview: previewEquipment,        // Full equipment state at next level
    changes: changedProperties,       // ['maxCharges'], ['damage'], etc
    description: upgrade.description, // Human-readable upgrade description
    level: nextLevel,                 // Level number (1-3)
  };
}

/**
 * Check if equipment can be upgraded
 */
export function canUpgradeEquipment(equipment, equipmentDef = null) {
  if (!equipmentDef) {
    equipmentDef = getEquipmentDefinition(equipment.id);
  }
  return equipment.upgradeLevel < 3 && equipmentDef.upgrades?.[`level${equipment.upgradeLevel + 1}`];
}

/**
 * Check if equipment can be scrapped
 */
export function canScrapEquipment(equipment, equipmentDef = null) {
  if (!equipmentDef) {
    equipmentDef = getEquipmentDefinition(equipment.id);
  }
  return !equipmentDef.cannotScrap;
}
```

**Game Move: Apply Upgrade**

In `CombatGame.js` loot phase:

```javascript
upgradeEquipment: ({ G, events, effects }, equipmentId) => {
  const equipment = G.player.equipment[equipmentId];
  const def = getEquipmentDefinition(equipmentId);
  
  // Validation
  if (!equipment || !def) return;
  if (G.player.upgradePoints < 1) {
    effects.showMessage('Not enough upgrade points!');
    return;
  }
  if (equipment.upgradeLevel >= 3) {
    effects.showMessage('Already at max level!');
    return;
  }
  
  const nextLevel = equipment.upgradeLevel + 1;
  const upgrade = def.upgrades?.[`level${nextLevel}`];
  if (!upgrade) {
    effects.showMessage('No upgrade available!');
    return;
  }
  
  // Apply upgrade properties to equipment instance in game state
  Object.keys(upgrade).forEach(key => {
    if (key !== 'description') {
      equipment[key] = upgrade[key];
    }
  });
  
  // Update level and spend point
  equipment.upgradeLevel = nextLevel;
  G.player.upgradePoints -= 1;
  
  effects.showMessage(`${equipment.name} upgraded to level ${nextLevel}!`);
},

scrapEquipment: ({ G, effects }, equipmentId) => {
  const equipment = G.player.equipment[equipmentId];
  const def = getEquipmentDefinition(equipmentId);
  
  // Validation
  if (!equipment || !def) return;
  if (def.cannotScrap) {
    effects.showMessage('Cannot scrap this item!');
    return;
  }
  
  // Remove from equipment and grant upgrade point
  delete G.player.equipment[equipmentId];
  G.player.upgradePoints += 1;
  
  // Clear selection if this was selected
  if (G.loot?.selectedEquipment === equipmentId) {
    G.loot.selectedEquipment = null;
  }
  
  effects.showMessage(`${equipment.name} scrapped for +1 upgrade point!`);
},
```

### 3. UI Component Structure

**Main Component**: `LootBoard.jsx`

```javascript
import React from 'react';
import { EffectsBoardWrapper } from 'bgio-effects/react';
import EquipmentCard from './equipment/EquipmentCard';
import UpgradeWorkspace from './loot/UpgradeWorkspace';
import '../styles/Loot.css';

const LootBoard = ({ G, ctx, moves, events, reset }) => {
  const [selectedEquipment, setSelectedEquipment] = React.useState(null);
  
  // Get selected equipment data
  const selectedEq = selectedEquipment ? G.player.equipment[selectedEquipment] : null;
  
  return (
    <div className="loot-board">
      {/* Top Section: Upgrade Workspace */}
      <div className="workspace-section">
        {selectedEq ? (
          <UpgradeWorkspace
            equipmentId={selectedEquipment}
            equipment={selectedEq}
            upgradePoints={G.player.upgradePoints}
            onScrap={() => {
              moves.scrapEquipment(selectedEquipment);
              setSelectedEquipment(null);
            }}
            onUpgrade={() => moves.upgradeEquipment(selectedEquipment)}
            onUse={() => {
              moves.useConsumable(selectedEquipment);
              setSelectedEquipment(null);
            }}
            onDeselect={() => setSelectedEquipment(null)}
          />
        ) : (
          <div className="workspace-idle">
            <h2>Select equipment below to upgrade or scrap</h2>
            <div className="upgrade-points-display">
              Upgrade Points: {G.player.upgradePoints}
            </div>
            <button 
              className="continue-button"
              onClick={() => moves.continueToNextEncounter()}
            >
              Continue
            </button>
          </div>
        )}
      </div>
      
      {/* Bottom Section: Equipment Tableau (same as combat) */}
      <div className="player-section">
        <div className="player-tableau">
          <h3>Equipment</h3>
          <div className="equipment-list">
            {Object.entries(G.player.equipment).map(([id, equipment]) => (
              <EquipmentCard
                key={id}
                equipmentId={id}
                equipment={equipment}
                G={G}
                handlers={{
                  onSelect: () => {
                    if (selectedEquipment === id) {
                      setSelectedEquipment(null);
                    } else {
                      setSelectedEquipment(id);
                    }
                  },
                  disabled: false
                }}
                isSelected={selectedEquipment === id}
              />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default EffectsBoardWrapper(LootBoard, {
  updateStateAfterEffects: true
});
```

**Upgrade Workspace Component**: `src/components/loot/UpgradeWorkspace.jsx`

```javascript
import React from 'react';
import { getEquipmentDefinition } from '../../game/cards';
import { getUpgradePreview, canUpgradeEquipment, canScrapEquipment } from '../../game/helpers/upgrades';
import EquipmentCard from '../equipment/EquipmentCard';

const UpgradeWorkspace = ({ equipmentId, equipment, upgradePoints, onScrap, onUpgrade, onUse, onDeselect }) => {
  const def = getEquipmentDefinition(equipmentId);
  const upgradePreview = getUpgradePreview(equipment, def);
  const canUpgrade = upgradePreview && upgradePoints >= 1;
  const canScrap = canScrapEquipment(equipment, def);
  const isConsumable = equipment.type === 'consumable';
  const isHealthConsumable = isConsumable && def.effect?.toString().includes('hp'); // Simple heuristic
  
  return (
    <div className="upgrade-workspace">
      <button className="deselect-btn" onClick={onDeselect}>✕</button>
      
      <div className="upgrade-comparison">
        {/* Current State */}
        <div className="current-state">
          <h3>Current (Level {equipment.upgradeLevel})</h3>
          <EquipmentCard
            equipmentId={equipmentId}
            equipment={equipment}
            handlers={{ disabled: true }}
            isPreview={true}
          />
          <div className="stats-display">
            {equipment.damage !== undefined && <div>Damage: {equipment.damage}</div>}
            {equipment.maxCharges !== undefined && <div>Max Charges: {equipment.maxCharges}</div>}
            {/* Add other relevant stats */}
          </div>
        </div>
        
        {/* Arrow */}
        {upgradePreview && (
          <div className="upgrade-arrow">
            <div className="arrow">→</div>
            <div className="cost">1 Upgrade Point</div>
          </div>
        )}
        
        {/* Next Level Preview */}
        {upgradePreview ? (
          <div className="preview-state">
            <h3>Next Level ({upgradePreview.level})</h3>
            <EquipmentCard
              equipmentId={equipmentId}
              equipment={upgradePreview.preview}
              handlers={{ disabled: true }}
              isPreview={true}
            />
            <div className="stats-display">
              {upgradePreview.changes.map(prop => (
                <div key={prop} className="stat-change highlighted">
                  {prop === 'damage' && `Damage: ${equipment.damage} → ${upgradePreview.preview.damage}`}
                  {prop === 'maxCharges' && `Max Charges: ${equipment.maxCharges} → ${upgradePreview.preview.maxCharges}`}
                  {/* Add other properties */}
                </div>
              ))}
            </div>
            <div className="upgrade-description">{upgradePreview.description}</div>
          </div>
        ) : !isConsumable ? (
          <div className="max-level">
            <h2>MAX LEVEL</h2>
            <p>This equipment is fully upgraded!</p>
          </div>
        ) : null}
      </div>
      
      {/* Action Buttons */}
      <div className="action-buttons">
        {canScrap && (
          <button onClick={onScrap} className="scrap-btn">
            SCRAP (+1 Upgrade Point)
          </button>
        )}
        {!isConsumable && (
          <button 
            onClick={onUpgrade} 
            className="upgrade-btn"
            disabled={!canUpgrade}
          >
            UPGRADE (Costs 1 Point)
          </button>
        )}
        {isHealthConsumable && (
          <button onClick={onUse} className="use-btn">
            USE NOW
          </button>
        )}
      </div>
    </div>
  );
};

export default UpgradeWorkspace;
```

### 4. Handling Different Equipment Types

The system is **fully data-driven**:

**Consumables**:
- No `upgrades` property in definition
- `getUpgradePreview()` returns `null`
- UI only shows "SCRAP" and "USE" buttons (if health consumable)

**Weapons/Gear**:
- Have `upgrades` property with level1-level3
- `getUpgradePreview()` returns full preview object
- UI shows "SCRAP" and "UPGRADE" buttons

**Starting Gear** (Charger):
- Has `cannotScrap: true` in definition
- `canScrapEquipment()` returns `false`
- UI hides/disables scrap button

**Adding New Items**:
Just add to card definitions with upgrade paths - no UI code changes needed!

### 5. Phase Routing

In `App.jsx` or main game component:

```javascript
import CombatBoard from './components/CombatBoard';
import LootBoard from './components/LootBoard';

function GameUI({ G, ctx, moves, events, reset }) {
  if (ctx.phase === 'combat') {
    return <CombatBoard G={G} ctx={ctx} moves={moves} events={events} reset={reset} />;
  }
  
  if (ctx.phase === 'loot') {
    return <LootBoard G={G} ctx={ctx} moves={moves} events={events} reset={reset} />;
  }
  
  return <div>Unknown phase: {ctx.phase}</div>;
}
```

---

## Edge Cases & Considerations

1. **Cannot Scrap Starting Gear**: Charger has `cannotScrap: true`
2. **Consumables Cannot Upgrade**: Only show scrap/use options
3. **Max Level Items**: Show "MAX LEVEL" instead of upgrade preview
4. **No Upgrade Points**: Disable upgrade button, show "Need upgrade points"
5. **Empty Inventory**: Should never happen, but handle gracefully
6. **Multiple Same Items**: Each needs unique instance ID

---

## Future Enhancements

- **Elevator Decision**: If elevator unlocked, show "Take Elevator" vs "Continue on Level"
- **Orb Display**: Show orbs collected during loot phase
- **Compare Items**: Side-by-side comparison mode for similar items
- **Undo**: Allow undo of scrap/upgrade decisions before continuing
- **Batch Actions**: Select multiple items to scrap at once
- **Tooltips**: Hover tooltips for detailed stat explanations
- **Sound Effects**: Scrap/upgrade/loot sounds for feedback

---

## Success Metrics

The design succeeds if:
- ✅ Players understand upgrade paths clearly
- ✅ No accidental scrapping (clear confirmation or undo)
- ✅ Smooth transition between combat and loot phases
- ✅ Spatial consistency maintained with combat screen
- ✅ Decision-making is satisfying and strategic
