# `BP_ItemPickup` — World Item Pickup Actor

**Parent Class:** `Actor`
**Category:** Inventory
**Target UE Version:** 5.5–5.7
**Build Phase:** 4 — Inventory
**C++ Status:** 🔵 BP-Only

> **Concrete step-by-step examples** of building specific item pickups (flashlight, pistol, medkit, keycard) with exact Blueprint graphs are in [`docs/game/`](../../game/README.md). The spec below defines the full architecture; the game examples show you exactly what nodes to connect.

---

## 0. Quick Setup — How to Place an Item in the World

This is the most common question: "I created a `DA_ItemData` but I can't drag it into the level." Here's the correct workflow:

### Step A — Create the Data Asset (one-time per item type)

```
Content Browser → Framework/DataAssets/Items/
  Right-click → Miscellaneous → Data Asset
  Class: DA_ItemData
  Name: DA_Item_MedKit
  Fill in: ItemTag, DisplayName, Icon, WorldMesh, Weight, StackLimit, ItemType
  If ItemType=Consumable → fill ConsumableData (HealthRestore=25, UseDuration=2.0)
  Save
```

### Step B — Create the BP_ItemPickup Blueprint (one-time)

```
Content Browser → Framework/Inventory/
  Right-click → Blueprint Class → Actor
  Name: BP_ItemPickup
  Implement I_Interactable interface
  Add: StaticMeshComponent (named "Mesh"), SphereComponent (named "InteractionCollision")
  Add: Config variable of type S_PickupConfig
  In Construction Script: read Config.ItemData → set Mesh to ItemData.WorldMesh
```

### Step C — Place Items in Your Level (repeat per item instance)

```
1. Drag BP_ItemPickup into the level
2. Select it → Details panel → Config → Item Data → DA_Item_MedKit
3. Set Quantity → 1 (or more for stacked items)
4. Position it where you want it in the world
```

The `BP_ItemPickup` reads the mesh, name, icon, and interaction prompt from the `DA_ItemData`. You never drag the Data Asset itself into the level — only the actor that references it.

```
DA_Item_MedKit (Content Browser)        ← defines WHAT
        ↑ referenced by
BP_ItemPickup (Actor in level)          ← physical body in world
        ↑ interacts via
Player → BPC_InteractionDetector → I_Interactable → BPC_InventorySystem.AddItem()
```

---

## 1. Overview

`BP_ItemPickup` is a world-placed or runtime-spawned `Actor` representing an item the player can pick up. It implements [`I_Interactable`](../01-core/03_I_InterfaceLibrary.md) and optionally [`I_Persistable`](../01-core/03_I_InterfaceLibrary.md).

When the player interacts (via [`BPC_InteractionDetector`](../03-interaction/16_BPC_InteractionDetector.md)), the pickup calls `BPC_InventorySystem.AddItem` with the associated item data, plays feedback, and either destroys itself or depletes a stack count.

---

## 2. Enums

### `E_PickupSpawnReason`

| Value | Description |
|-------|-------------|
| `PlacedInLevel` | Designer-placed in the map. |
| `DroppedFromInventory` | Player dropped from inventory. |
| `LootDrop` | Spawned as loot from a creature/container. |
| `QuestReward` | Spawned as a quest completion reward. |

### `E_PickupVisualState`

| Value | Description |
|-------|-------------|
| `Idle` | Default floating/rotating state. |
| `Highlighted` | Within interaction range; glowing outline. |
| `BeingPickedUp` | Playing pickup animation before destruction. |
| `Respawning` | Hidden while respawn timer counts down. |

---

## 3. Structs

### `S_PickupConfig`

| Field | Type | Description |
|-------|------|-------------|
| `ItemData` | `DA_ItemData*` | Primary item data asset reference. |
| `Quantity` | `int32` | Stack quantity (1 for non-stackable). |
| `SpawnReason` | `E_PickupSpawnReason` | Initial spawn reason. |
| `bIsInfinite` | `bool` | If true, item is never consumed on pickup. |
| `bRespawns` | `bool` | If true, re-appears after a timer. |
| `RespawnTimeSeconds` | `float` | Seconds before respawning (in-game or real-time based on config). |
| `bUsePhysicsOnDrop` | `bool` | If true, dropped items have physics simulation. |
| `DropVelocity` | `FVector` | Initial velocity when dropped from inventory. |
| `bAutoRotate` | `bool` | Whether the pickup rotates slowly while idle. |
| `RotationRate` | `FRotator` | Rotation speed when auto-rotate is enabled. |
| `bBobUpDown` | `bool` | Whether the pickup bobs up and down. |
| `BobAmplitude` | `float` | Bobbing height offset. |
| `BobFrequency` | `float` | Bobbing speed. |

### `S_PickupWorldState`

| Field | Type | Description |
|-------|------|-------------|
| `SpawnTransform` | `FTransform` | Transform at spawn time (for respawn reference). |
| `SpawnTime` | `float` | Game time at spawn. |
| `bHasBeenPickedUp` | `bool` | Whether pickup has ever been collected. |
| `PickedUpBy` | `AActor*` | Last player to pick up this item. |

---

## 4. Variables

### Configuration (Instance Editable)

| Variable | Type | Description |
|----------|------|-------------|
| `Config` | `S_PickupConfig` | Primary configuration. |
| `bAutoSetup` | `bool` | If true, auto-configures mesh and collision at `BeginPlay`. |
| `PickupWidgetClass` | `TSubclassOf<UUserWidget>` | Optional widget class for pickup prompt. |

### Scene Components (Create & Attach at Construction)

| Variable | Type | Description |
|----------|------|-------------|
| `RootScene` | `USceneComponent*` | Root component. |
| `MeshComponent` | `UStaticMeshComponent*` | Visual representation of item. |
| `InteractionCollision` | `USphereComponent*` | Overlap sphere for interaction detection. |
| `FloatCurveComponent` | `UFloatingPawnMovement*` | Optional floating/bobbing behaviour component. |

### State (Blueprint Read Only, Replicated)

| Variable | Type | Description |
|----------|------|-------------|
| `VisualState` | `E_PickupVisualState` | Current visual state. |
| `bIsAvailable` | `bool` | Whether the pickup can be collected. |

### Internal (Blueprint Read Only)

| Variable | Type | Description |
|----------|------|-------------|
| `WorldState` | `S_PickupWorldState` | Tracks pickup history. |
| `OwningInventory` | `UBPC_InventorySystem*` | Cached when player overlaps interaction trigger. |
| `RespawnTimerHandle` | `FTimerHandle` | Handle for respawn delay. |

---

## 5. Functions & Events

### Public Functions

| Function | Description |
|----------|-------------|
| `Public Functions` | Description |
| `Interact_Implementation` | Implements `I_Interactable`: calls `BPC_InventorySystem.AddItem()`, plays feedback, destroys or depletes. |
| `OnDroppedFromInventory` | Called by inventory drop system: sets transform, velocity, and respawn behaviour. |
| `BeginPlay` | Caches references, sets up bobbing/rotation timeline, configures collision. |
| `SetPickupEnabled` | Toggles visibility and collision. |
| `StartRespawn` | Hides pickup and starts countdown timer. |
| `OnRespawnComplete` | Restores pickup to world (visual + collision). |
| `GetPickupDisplayInfo` | Returns `FText` name and `UTexture2D*` icon for UI prompt. |

### Protected Functions

| Function | Description |
|----------|-------------|
| `OnOverlapBegin` | When player enters overlap: highlight, show pickup prompt. |
| `OnOverlapEnd` | When player leaves overlap: unhighlight, hide pickup prompt. |
| `OnPickupAnimationComplete` | Called after pickup animation ends (destroys actor or hides). |
| `PlayPickupFeedback` | Plays sound, particle, and/or widget animation. |

### Event Dispatchers

| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnPickupAvailableChanged` | `bool bIsAvailable` | Broadcast when pickup becomes available/unavailable. |
| `OnPickupCollected` | `AActor* Collector` | Broadcast when item is successfully collected. |
| `OnPickupRespawnStarted` | `float RespawnTime` | Broadcast when respawn timer begins. |
| `OnPickupRespawned` | — | Broadcast when pickup reappears. |

---

## 6. Blueprint Graph Flow

```
Event BeginPlay
    → Cache WorldState.SpawnTransform = ActorTransform
    → If bAutoSetup → Set MeshComponent from ItemData
    → Configure collision presets (OverlapOnlyPawn)
    → Attach Timeline for bobbing / rotation
    → Start idle loop

OnOverlapBegin (Player overlaps InteractionCollision)
    → Set VisualState = Highlighted
    → Show pickup prompt widget (if assigned)
    → Cache player's BPC_InventorySystem

OnOverlapEnd (Player leaves InteractionCollision)
    → Set VisualState = Idle
    → Hide pickup prompt widget
    → Clear cached inventory component reference

Interact_Implementation (Called from BPC_InteractionDetector)
    → If !bIsAvailable → return (no interaction)
    → Validate player inventory has space → if full, show "Inventory Full" feedback → return
    → Set VisualState = BeingPickedUp
    → Play pickup sound + particle effect
    → Call BPC_InventorySystem.AddItem(Config.ItemData, Config.Quantity)
    → If AddItem succeeded:
        → Broadcast OnPickupCollected(InteractingPlayer)
        → If bIsInfinite → do not destroy
        → Else → Deplete stack or destroy
        → If bRespawns → StartRespawn
        → Else → DestroyActor
    → Else:
        → Set VisualState = Idle
        → Show error feedback

OnDroppedFromInventory (ItemData, Quantity, DropLocation, DropVelocity)
    → Set Config with ItemData and Quantity
    → Set Config.SpawnReason = DroppedFromInventory
    → Set ActorTransform = DropLocation
    → If bUsePhysicsOnDrop → Enable physics on MeshComponent, apply velocity
    → Enable collision and visibility
    → Set bIsAvailable = true

StartRespawn
    → Set bIsAvailable = false
    → Hide MeshComponent, disable collision
    → Broadcast OnPickupRespawnStarted(RespawnTimeSeconds)
    → Start timer (RespawnTimerHandle, OnRespawnComplete, RespawnTimeSeconds)

OnRespawnComplete
    → Show MeshComponent, enable collision
    → Set bIsAvailable = true
    → Set VisualState = Idle
    → Broadcast OnPickupRespawned
```

---

## 7. Replication

| Variable | Replication | Callback |
|----------|-------------|----------|
| `bIsAvailable` | `Replicated` | — |
| `VisualState` | `Replicated Using` | `OnRep_VisualState` |
| `Config.Quantity` | `Replicated` | — |
| `WorldState.SpawnTransform` | `Replicated` | — |

---

## 8. Dependencies & Communication

| System | Relationship |
|--------|--------------|
| `I_Interactable` | Implements the interface for interaction detection. |
| `BPC_InteractionDetector` | Sends overlap events and routes interaction call. |
| `BPC_InventorySystem` (31) | **Target for item addition.** C++ component — call `AddItem(ItemData, Quantity)`. |
| `DA_ItemData` (07) | Supplies mesh, name, icon, stack limits, weight. |
| `BPC_PlayerMetricsTracker` (15) | Logs pickup event (item type, quantity, location). |
| `I_Persistable` | Optional: saves pickup state (available, transform, quantity). |
| `BPC_KeyItemSystem` (34) | Checks `bIsKeyItem` — key items auto-protect from drop/clear. |
| `SS_AchievementSystem` (103) | Notified on collectible pickups for completion tracking. |

---

## 9. Success Criteria

1. World-placed pickup shows mesh and collision at game start.
2. Player overlaps pickup → highlight activates + prompt widget shows.
3. Player leaves overlap → highlight deactivates + prompt hides.
4. Player interacts → item added to inventory, feedback plays, pickup destroyed.
5. Dropped from inventory → pickup spawns at correct transform with physics velocity.
6. Infinite pickups never deplete on collection.
7. Respawn pickups re-appear after configured timer.
8. Respawning pickups hide collision and mesh during cooldown.
9. Multiplayer: pickups replicate state to all clients.
10. Pickup prompt displays correct item name and icon.
11. No interaction if player inventory is full (feedback shown).

---

## 10. Data Flow Summary

```
Player approaches world item → Overlap event
    → BPC_InteractionDetector → BP_ItemPickup sets VisualState = Highlighted
    → Show pickup prompt widget
Player presses Interact key
    → BPC_InteractionDetector.InteractTarget → BP_ItemPickup.Interact_Implementation
    → Validate availability + inventory space
    → BPC_InventorySystem.AddItem (ItemData, Quantity)
    → Play pickup sound + particle
    → Broadcast OnPickupCollected
    → If bRespawns → StartRespawn (hide, wait, reappear)
    → Else → DestroyActor