# Item Example — Flashlight (Tool)

**Item Type:** `Tool`
**Complexity:** Medium
**Systems Used:** `DA_ItemData`, `BP_ItemPickup`, `I_UsableItem`, `I_Toggleable`, `BPC_InventorySystem`, `BPC_EquipmentSlotSystem`
**What You Learn:** Data Asset setup, pickup actor with soft reference mesh, Construction Script wiring, toggleable active-use item, inventory integration

---

## 1. Create the DA_ItemData

### 1.1 — Create the Data Asset

```
Content Browser → Game/Items/
  (create folder "Items" if needed)
  Right-click → Miscellaneous → Data Asset
  Class: DA_ItemData
  Name: DA_Item_Flashlight
```

### 1.2 — Fill Core Properties

Open `DA_Item_Flashlight`:

| Property | Value | Notes |
|----------|-------|-------|
| `Item Tag` | `Framework.Item.Tool.Flashlight` | Must be registered in `DA_GameTagRegistry`. Tag hierarchy: Framework → Item → Tool → Flashlight |
| `Display Name` | "Flashlight" | Player sees this in inventory UI |
| `Description` | "A heavy-duty tactical flashlight. Click to toggle on/off." | Shown in inventory |
| `Icon` | `T_Flashlight_Icon` | Assign any texture; for prototype, use a white square |
| `World Mesh` | `SM_Flashlight` | **Soft reference** — doesn't need to be loaded at startup; Construction Script resolves it |
| `Weight` | `1.5` | Carried weight in your carry limit |
| `Stack Limit` | `1` | Cannot stack multiple flashlights |
| `Item Type` | `Tool` | Determines that `Equipment Data` panel shows |

### 1.3 — Fill Equipment Data

Scroll down — the `Equipment Data` panel appears because `ItemType == Tool`:

| Field | Value | Notes |
|-------|-------|-------|
| `Slot` | `Framework.Equipment.Slot.Tool` | Which equipment slot it goes into |
| `Damage` | `0` | Not a weapon |
| `Fire Rate` | `0` | Not a weapon |
| `Range` | `0` | N/A |
| `Magazine Size` | `0` | N/A |
| `Reload Time` | `0` | N/A |

### 1.4 — Save

File → Save (or Ctrl+S). The Data Asset is ready.

---

## 2. Create the BP_Pickup_Flashlight (World Pickup Actor)

This is the actor the player sees in the level. It reads the Data Asset and represents it in the world.

### 2.1 — Create Blueprint

```
Content Browser → Game/Pickups/
  (create folder "Pickups" if needed)
  Right-click → Blueprint Class → Actor
  Name: BP_Pickup_Flashlight
```

### 2.2 — Add Components

Open `BP_Pickup_Flashlight` → **Viewport** tab.

**Add Component** button (top-left of the Components panel):

| Order | Component Class | Name | Purpose |
|-------|----------------|------|---------|
| 1 | `StaticMeshComponent` | `Mesh` | Renders the flashlight 3D model in the world |
| 2 | `SphereComponent` | `PickupTrigger` | Detects when player is close enough to interact |
| 3 | *(Optional)* `PointLightComponent` | `BatteryIndicator` | Small glow showing the pickup has charge |

**Select `PickupTrigger` → Details:**
- `Sphere Radius` → `200.0`
- **Collision → Collision Presets** → `OverlapOnlyPawn`

**Select `Mesh` → Details:**
- **Collision → Collision Enabled** → `No Collision` (the sphere handles interaction; mesh collision is unnecessary)

Your Components panel should look like:

```
BP_Pickup_Flashlight (self)
  ├── DefaultSceneRoot
  ├── Mesh                  ← StaticMeshComponent
  ├── PickupTrigger         ← SphereComponent (radius 200)
  └── BatteryIndicator      ← PointLightComponent (optional)
```

### 2.3 — Create the ItemData Variable

In the **My Blueprint** panel (left side):

1. Click **+ Variable** → name: `ItemData` → type: **DA_ItemData → Object Reference**
2. Select the variable → Details:
   - **Instance Editable** → ✓
   - **Category** → `Pickup`
   - **Tooltip** → "The item Data Asset this pickup represents"

This is simpler than using a struct for a single item — you can expand to a struct later if you need more fields.

### 2.4 — Wire the Construction Script

Switch to the **Construction Script** tab (or open the graph). This runs when the blueprint is compiled or when you change `ItemData` in the editor.

```
[Construction Script]
  │
  ├─ ItemData (drag from My Blueprint → Get ItemData)
  │
  ├─ Is Valid? (ItemData)
  │    │
  │    ├─ Branch (Condition = IsValid result)
  │    │
  │    ├─ True:
  │    │    │
  │    │    ├─ ItemData → Get World Mesh
  │    │    │     This returns a TSoftObjectPtr<UStaticMesh>
  │    │    │     │
  │    │    │     └─ To Soft Object Reference (conversion node, or just drag from pin)
  │    │    │          └─ Resolve Soft Reference (or "Async Load Asset")
  │    │    │               │
  │    │    │               ├─ On Complete (if async) → Set Static Mesh (Mesh component, New Mesh = loaded asset)
  │    │    │               │
  │    │    │               └─ For Construction Script, use "Load Synchronous" to see it in editor immediately:
  │    │    │                    └─ Sync Load Asset (from soft ref) → Set Static Mesh (Mesh)
  │    │    │
  │    │    ├─ ItemData → Get Display Name → Set Actor Label
  │    │    │     (This renames the actor in the world to "Flashlight" so it's easy to find in the World Outliner)
  │    │    │
  │    │    └─ ItemData → Get Weight → (optional: store for physics if dropped)
  │    │
  │    └─ False:
  │         └─ Print String ("No ItemData assigned to BP_Pickup_Flashlight")
  │              └─ Only if Editor (not PIE/standalone)
```

**Exact node sequence:**

| Step | Right-click / Drag | Search | Connect |
|------|-------------------|--------|---------|
| 1 | Drag `ItemData` variable → Get | — | — |
| 2 | Drag from ItemData pin | `Is Valid` | Branch Condition |
| 3 | True branch → drag from ItemData | `Get World Mesh` | — |
| 4 | Drag from World Mesh pin | `Load Synchronous` | — |
| 5 | Drag `Mesh` component from Components → Get | — | Target of Set Static Mesh |
| 6 | Drag from Load Synchronous Return Value | `Set Static Mesh` (New Mesh) | — |
| 7 | Drag from ItemData → `Get Display Name` | — | To String (Auto) |
| 8 | Drag from string result | `Set Actor Label` → New Actor Label | — |

### 2.5 — Add I_Interactable Interface

1. **Class Settings** (toolbar button)
2. **Implemented Interfaces** → **Add** → search and select `UInteractable`
3. **Compile** (blue checkmark). Now these events appear:

#### Event Interact

```
Event Interact (Interface -> UInteractable)
  │ Interactor: AActor*
  │ Return Node expects a Boolean
  │
  ├─ Interactor → Get Component by Class → Class: UBPC_InventorySystem
  │    │
  │    └─ Is Valid?
  │         ├─ False → Return False (no inventory on this actor)
  │         │
  │         └─ True → [InventorySystem ref]
  │              │
  │              ├─ ItemData → Is Valid?
  │              │    └─ False → Return False
  │              │
  │              ├─ [InventorySystem] → Can Add Item
  │              │    ├─ Item: ItemData
  │              │    ├─ Quantity: 1
  │              │    └─ Result → Branch
  │              │         ├─ True:
  │              │         │    ├─ [InventorySystem] → Add Item (Item=ItemData, Quantity=1)
  │              │         │    │    → Result (int32, ignore)
  │              │         │    ├─ Destroy Actor
  │              │         │    └─ Return True
  │              │         └─ False:
  │              │              ├─ Print String ("Inventory full or cannot carry")
  │              │              └─ Return False
```

#### Event Can Interact

```
Event Can Interact (Interface -> UInteractable)
  │ Interactor: AActor*
  │ OutBlockReason: FText& (by reference)
  │ Return Node expects Boolean
  │
  ├─ ItemData → Is Valid?
  │    ├─ False → OutBlockReason = "No item data configured" → Return False
  │    └─ True → Return True
```

#### Event Get Interaction Prompt

```
Event Get Interaction Prompt (Interface -> UInteractable)
  │ Return Node expects FText
  │
  ├─ ItemData → Get Display Name
  ├─ Format Text: "Pick up {0}" (format with DisplayName)
  └─ Return the formatted text
```

### 2.6 — Optional: Bobbing & Rotation

In **Event Graph → Event BeginPlay**:

```
Event BeginPlay
  │
  ├─ Mesh → Set Collision Enabled → No Collision
  ├─ PickupTrigger → Set Collision Enabled → Query Only
  │
  ├─ [Create a Timeline named "FloatAnim"]
  │    │
  │    ├─ Float Track: 0.0 to 1.0, length 2.0 seconds, Looping ✓
  │    │
  │    └─ Timeline → Update pin:
  │         │
  │         ├─ Mesh → Add World Rotation
  │         │    ├─ Delta Rotation: (0, 0, TimelineOutput * 90.0)
  │         │    └─ Sweep: false, Teleport: false
  │         │
  │         └─ Mesh → Set World Location (interpolation)
  │              └─ Z = ActorLocation.Z + sin(TimelineOutput * 2π) * 5.0
  │                   (Use "Make Vector" → Break Actor Location → modify Z → "Lerp" or direct set)
  │
  └─ Play Timeline from Start
```

> For the bobbing math: `sin(TimelineOutput * 6.28318) * 5.0` gives a smooth ±5 unit bounce.

---

## 3. Create the BP_Flashlight (Active-Use Actor — Toggleable)

This is a separate Blueprint for the *held* flashlight — what the player actually uses after picking it up. It implements `I_UsableItem` and `I_Toggleable`.

### 3.1 — Create Blueprint

```
Content Browser → Game/Actors/
  Right-click → Blueprint Class → Actor
  Name: BP_Flashlight
```

### 3.2 — Add Components

| # | Component | Name | Purpose |
|---|-----------|------|---------|
| 1 | `StaticMeshComponent` | `BodyMesh` | Flashlight body |
| 2 | `SpotLightComponent` | `LightBeam` | The actual light cone |
| 3 | `AudioComponent` | `ClickSound` | Plays the toggle click sound |

Select `LightBeam` → Details:
- `Intensity` → `5000.0` (bright)
- `Inner Cone Angle` → `15.0`
- `Outer Cone Angle` → `30.0`
- **Visible** → false (starts off — player toggles it on)

### 3.3 — Add Toggle State Variable

**+ Variable** → Name: `bIsOn` → Type: `Boolean` → Default: `false`
- **Replication** → `Replicated` (if multiplayer)

### 3.4 — Add Interfaces

Class Settings → Interfaces → Add:
- `UUsableItem` — so the player can select and use it from inventory
- `UToggleable` — so the player can toggle it on/off

### 3.5 — Wire I_Toggleable

```
Event Toggle (Interface -> UToggleable)
  │ Toggler: AActor*
  │
  ├─ bIsOn = NOT bIsOn  (FlipFlop or Boolean NOT)
  │
  ├─ Branch (bIsOn)
  │    ├─ True:
  │    │    ├─ LightBeam → Set Visibility (true)
  │    │    ├─ ClickSound → Play
  │    │    └─ (Optional) Play toggle-on animation montage
  │    │
  │    └─ False:
  │         ├─ LightBeam → Set Visibility (false)
  │         └─ ClickSound → Play

Event Set State (Interface -> UToggleable)
  │ bNewState: Boolean, Setter: AActor*
  │
  ├─ Set bIsOn = bNewState
  ├─ LightBeam → Set Visibility (bNewState)
  └─ (Don't play click sound — this is programmatic, not player toggle)

Event Get Current State
  │ Return Boolean
  └─ Return bIsOn

Event Get State Label
  │ Return FText
  └─ Format Text: "Flashlight is {0}" → format with (bIsOn ? "ON" : "OFF")
```

### 3.6 — Wire I_UsableItem

```
Event Use Item (Interface -> UUsableItem)
  │ User: AActor*, Target: AActor*
  │ Return Boolean
  │
  ├─ Call Toggle (self, User)   ← reuses the I_Toggleable logic
  └─ Return True

Event Can Use Item
  │ User, Target
  │ Return Boolean
  └─ Return True  (can always toggle flashlight)

Event Get Use Duration
  │ Return Float
  └─ Return 0.0  (instant toggle)

Event On Item Used
  │ User: AActor*
  │
  └─ (Optional) Play a small haptic pulse on controller
```

### 3.7 — Compile & Save

The held flashlight is ready. When a player picks up `BP_Pickup_Flashlight` and the inventory's `BPC_ActiveItemSystem` routes the item to use, it calls `I_UsableItem.UseItem()` on this actor, which toggles the light.

---

## 4. Wire Inventory Integration

### 4.1 — In Your Player Pawn BP

When `BPC_ActiveItemSystem` detects that an item of type `Tool` is used:
1. Get the equipped item from `BPC_EquipmentSlotSystem`
2. Spawn `BP_Flashlight` actor (if not already spawned)
3. Call `I_UsableItem.UseItem()`
4. The flashlight actor handles its own toggle state

### 4.2 — Quick Test Without Full Integration

For a rapid prototype, add this to your **PlayerCharacter's Event Graph**:

```
Event InputAction (IA_UseItem, Pressed)
  │
  ├─ Branch (bFlashlightEquipped)   ← set this bool when flashlight is picked up
  │    ├─ True:
  │    │    ├─ Get All Actors of Class (BP_Flashlight)
  │    │    ├─ For Each → Call I_Toggleable.Toggle
  │    │    └─ (In production, use BPC_ActiveItemSystem instead of this crude search)
  │    └─ False: do nothing
```

---

## 5. Verification Checklist

**Step 1 — Data Asset:** Open `DA_Item_Flashlight` → all fields filled, no blank properties.

**Step 2 — Pickup in Editor:** Drag `BP_Pickup_Flashlight` into level → set `ItemData` → the mesh appears in viewport immediately (Construction Script).

**Step 3 — Pickup Interaction (PIE):**
- [ ] Walk up to flashlight pickup → interaction prompt appears ("Pick up Flashlight")
- [ ] Press Interact → flashlight disappears from world
- [ ] Check log/print: `BPC_InventorySystem.AddItem` was called
- [ ] In debug: `Get All Items` on inventory → flashlight is in a slot

**Step 4 — Held Use:**
- [ ] Toggle via IA_UseItem → light turns on (visible in world)
- [ ] Toggle again → light turns off
- [ ] Click sound plays on each toggle

**Step 5 — Equipment Slot:**
- [ ] Flashlight occupies `Framework.Equipment.Slot.Tool` slot
- [ ] Cannot equip another tool while flashlight is in slot (slot type validation)

---

## 6. Common Issues

| Issue | Cause | Fix |
|-------|-------|-----|
| Mesh doesn't appear in Construction Script | Soft reference not loaded | Use `Load Synchronous` instead of `Async Load Asset` in Construction Script |
| Pickup doesn't respond to interaction | `UInteractable` interface not added | Class Settings → Interfaces → Add `UInteractable` → Compile |
| "Can Add Item" always returns false | `BPC_InventorySystem.MaxWeight` too low or `GridWidth/Height = 0` | Set MaxWeight to 0 (unlimited) for testing, or increase it |
| Light doesn't toggle | `bIsOn` variable not replicated or `I_Toggleable` not wired | Verify `Toggle` event is called; check `Set Visibility` target is the correct light component |
| "No ItemData configured" error | Forgot to set `ItemData` on the pickup instance in the level | Select the pickup → Details → set ItemData → recompile |
