# `BPC_ContainerInventory` — Container / Loot Storage

**Parent Class:** `ActorComponent`
**Category:** Inventory
**Target UE Version:** 5.5–5.7
**Build Phase:** 3 — Inventory

---

## 1. Overview

`BPC_ContainerInventory` provides an inventory for world actors like loot crates, drawers, cabinets, corpses, and safe storage. It shares the same `S_InventorySlot`/`S_InventoryEntry` structs as [`BPC_InventoryComponent`](docs/blueprints/04-inventory/22_BPC_InventoryComponent.md) but operates as a standalone container with no player controller — it is interacted with via [`BPC_InteractionDetector`](docs/blueprints/03-interaction/16_BPC_InteractionDetector.md) and transfers items to/from the player's inventory.

It supports lock state, loot tables (random fill from `DA_LootTable`), respawning, decay, and implements `I_Interactable` and `I_Persistable`.

---

## 2. Enums

### `E_ContainerLockState`

| Value | Description |
|-------|-------------|
| `Unlocked` | Anyone can open and loot. |
| `Locked` | Requires key or lockpick to open. |
| `Jammed` | Lock is broken; cannot be opened (visual only). |
| `KeyRequired` | Requires specific key item from inventory. |
| `PuzzleRequired` | Requires external puzzle completion. |

### `E_ContainerFillMethod`

| Value | Description |
|-------|-------------|
| `Fixed` | Contents defined in a `DA_FixedContainerContents` data asset. |
| `LootTable` | Contents generated from a `DA_LootTable`. |
| `Empty` | Starts empty; items placed manually by designer. |
| `PlayerStored` | Items stored by the player (drop-off box, cupboard). |

### `E_ContainerLootRarity`

| Value | Description |
|-------|-------------|
| `Trash` | Junk items, low-value resources. |
| `Common` | Standard consumables, basic resources. |
| `Uncommon` | Better gear, moderate resources. |
| `Rare` | Good weapons, valuable items. |
| `Legendary` | Unique story items, top-tier gear. |

---

## 3. Structs

### `S_ContainerConfig`

| Field | Type | Description |
|-------|------|-------------|
| `ContainerName` | `FText` | Display name shown in UI ("Wooden Crate", "File Cabinet"). |
| `MaxSlots` | `int32` | Number of inventory slots. |
| `FillMethod` | `E_ContainerFillMethod` | How contents are generated. |
| `LootTable` | `TArray<FName>` | Loot table IDs to roll on fill. |
| `LockState` | `E_ContainerLockState` | Starting lock state. |
| `RequiredKeyTag` | `FGameplayTag` | Required item tag if KeyRequired. |
| `bCanRespawnLoot` | `bool` | If true, loot respawns after a timer. |
| `RespawnTimeHours` | `float` | In-game hours before loot respawns. |
| `bDecayEnabled` | `bool` | If true, items decay and disappear over time. |
| `DecayTimeHours` | `float` | In-game hours before items decay entirely. |
| `bIsPlayerStorage` | `bool` | If true, items persist and are safe (player stash). |
| `bReplicates` | `bool` | Whether container state is replicated. |

### `S_ContainerLootEntry`

| Field | Type | Description |
|-------|------|-------------|
| `ItemData` | `DA_ItemData*` | Possible item to spawn. |
| `Weight` | `float` | Relative spawn weight for random selection. |
| `MinCount` | `int32` | Minimum stack count. |
| `MaxCount` | `int32` | Maximum stack count. |
| `Rarity` | `E_ContainerLootRarity` | Rarity tier for filtering. |
| `bGuaranteed` | `bool` | If true, guaranteed to spawn (bypassed weighted chance). |

---

## 4. Variables

### Configuration (Instance Editable)

| Variable | Type | Description |
|----------|------|-------------|
| `ContainerConfig` | `S_ContainerConfig` | Primary container configuration. |
| `FixedContents` | `TArray<FStartingItemEntry>` | Fixed items to place at BeginPlay. |

### State (Blueprint Read Only, Replicated)

| Variable | Type | Description |
|----------|------|-------------|
| `Slots` | `TArray<S_InventorySlot>` | Container inventory slots. |
| `LockState` | `E_ContainerLockState` | Current lock state. |
| `bIsLooted` | `bool` | True after initial loot has been taken. |
| `bIsOpen` | `bool` | Whether the container UI is open. |

### Internal (Not Replicated)

| Variable | Type | Description |
|----------|------|-------------|
| `OwningInventoryComponent` | `BPC_InventoryComponent*` | Cached reference to interacting player's inventory (set when opened). |
| `OwningActor` | `AActor*` | Cached owning actor (the container mesh). |
| `RespawnTimerHandle` | `FTimerHandle` | Handle for loot respawn timer. |

---

## 5. Functions & Events

### Public Functions

| Function | Description |
|----------|-------------|
| `Interact_Implementation` | Implements `I_Interactable`: opens container UI if conditions met. |
| `OpenContainer` | Called on interaction: sends `Slots` data to player's UI. |
| `CloseContainer` | Closes container UI, clears interacting player reference. |
| `AddItemToContainer` | Adds item to container slots (transfer from player). |
| `RemoveItemFromContainer` | Removes item from container (transfer to player). |
| `TryUnlock` | Attempts to unlock container with key/lockpick. |
| `GenerateLoot` | Generates container contents from loot table or fixed data. |
| `ClearContainer` | Empties all slots. |
| `IsContainerEmpty` | Returns true if all slots are empty. |
| `HasPlayerTransferTarget` | Returns true if a player is actively interacting with this container. |

### Protected Functions

| Function | Description |
|----------|-------------|
| `BeginPlay` | Caches references, calls `GenerateLoot` if fill method is `Fixed` or `LootTable`. |
| `ValidatePlayerInteraction` | Checks distance, lock state, player alive state. |
| `RollLootTable` | Performs weighted random selection from loot table. |
| `StartRespawnTimer` | Starts timer for loot respawn. |
| `OnRespawnTimer` | Calls `GenerateLoot` and refills slots. |
| `StartDecayTimer` | Starts timer for item decay. |
| `OnDecayTimer` | Removes all items, sets `bIsLooted = false`. |
| `OnRep_Slots` | RepNotify: updates UI on remote client. |

### Event Dispatchers

| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnContainerOpened` | `AActor* InteractingPlayer` | Fired when container is opened. |
| `OnContainerClosed` | — | Fired when container UI is closed. |
| `OnContainerItemAdded` | `S_InventoryEntry Item` | Fired on item transfer into container. |
| `OnContainerItemRemoved` | `S_InventoryEntry Item` | Fired on item transfer out of container. |
| `OnContainerUnlocked` | `AActor* Instigator` | Fired when container is unlocked. |
| `OnContainerLootGenerated` | — | Fired after loot generation. |

---

## 6. Blueprint Graph Flow

```
Event BeginPlay
    → Cache OwningActor
    → Create empty Slots array (MaxSlots)
    → If FillMethod == Fixed → Add FixedContents
    → If FillMethod == LootTable → Call GenerateLoot
    → If LockState != Unlocked → Set bIsLocked as appropriate

OpenContainer
    → ValidatePlayerInteraction → If fail → return
    → Set bIsOpen = true
    → Cache interacting player's inventory component
    → Broadcast OnContainerOpened
    → (BP implementation) Open UI widget showing container slots

CloseContainer
    → Set bIsOpen = false
    → Clear cached player inventory reference
    → Broadcast OnContainerClosed
    → If All slots empty → Set bIsLooted = true
    → If bIsLooted and bCanRespawnLoot → StartRespawnTimer
    → If bDecayEnabled and container has items → StartDecayTimer

GenerateLoot
    → Clear all slots
    → For each category in LootTable:
        → For each S_ContainerLootEntry:
            → If bGuaranteed → Add item to slot
            → Else → Random roll against Weight
            → If success → Random quantity between MinCount and MaxCount
            → Add to slot
    → Broadcast OnContainerLootGenerated

TryUnlock (ItemTag)
    → If LockState == KeyRequired and ItemTag == RequiredKeyTag:
        → Set LockState = Unlocked
        → Broadcast OnContainerUnlocked
        → Return true
    → Else → Return false

AddItemToContainer (ItemData, Quantity)
    → Find free slot → If none → return (container full)
    → Find existing stack → If found and not full → increment
    → Else → new slot
    → If bReplicates → Mark slots dirty
    → Broadcast OnContainerItemAdded

RemoveItemFromContainer (SlotIndex, Quantity)
    → Decrement stack, clear slot if zero
    → Broadcast OnContainerItemRemoved
```

---

## 7. Replication

| Variable | Replication | Callback |
|----------|-------------|----------|
| `Slots` | `RepNotify` | `OnRep_Slots` — refreshes UI on remote clients |
| `LockState` | `Replicated` | — |
| `bIsOpen` | `Replicated` | — |
| `bIsLooted` | `Replicated` | — |

---

## 8. Dependencies & Communication

| System | Relationship |
|--------|--------------|
| `BPC_InteractionDetector` | Detects container and routes interaction to `OpenContainer`. |
| `BPC_InventoryComponent` | Target for item transfers when player loots the container. |
| `DA_LootTable` | Data asset containing weighted loot entries. |
| `BPC_InventoryUIManager` | Receives container slot data for display. |
| `I_Persistable` | Container saves its inventory state for persistence. |
| `BPC_LeverPuzzleComponent` | May unlock container when puzzle is solved (`PuzzleRequired` lock state). |
| `BPC_PlayerMetricsTracker` | Logs loot acquisition events. |
| `BPC_AdaptiveDifficulty` | May adjust loot table weights based on difficulty. |

---

## 9. Success Criteria

1. Player interacts with container → UI opens showing contents.
2. Items can be transferred from container to player inventory.
3. Items can be transferred from player inventory to container.
4. Locked container plays feedback; unlocked with correct key.
5. Fixed containers spawn designer-defined items.
6. Loot-table containers generate random items with correct weighting.
7. Empty containers show empty slots correctly.
8. Respawn timer refills container after all loot is taken.
9. Decay timer clears items after configured time.
10. Multiplayer: container state syncs to all clients.
11. Save/load restores container inventory and lock state.

---

## 10. Data Flow Summary

```
Player approaches loot crate and presses Interact
    → BPC_InteractionDetector → BP_LootCrate.Interact_Implementation
    → BPC_ContainerInventory.OpenContainer
    → Validate distance, lock state, player alive
    → Send Slots array to UI
    → Player clicks item in container UI
    → BPC_ContainerInventory.RemoveItemFromContainer
    → BPC_InventoryComponent.AddItem (transfer)
    → Broadcast OnContainerItemRemoved
    → UI updates both panels