Files
UE5-Modular-Game-Framework/docs/game/item-medkit.md

198 lines
7.2 KiB
Markdown

# Item Example — MedKit (Consumable)
**Item Type:** `Consumable`
**Complexity:** Low
**Systems Used:** `DA_ItemData`, `BP_ItemPickup`, `BPC_InventorySystem`, `BPC_ConsumableSystem`, `BPC_HealthSystem`
**What You Learn:** Consumable Data Asset, pickup actor, health restore, stackable item, quick-slot use
---
## 1. Create the DA_ItemData
### 1.1 — Create the Data Asset
```
Content Browser → Game/Items/
Right-click → Miscellaneous → Data Asset
Class: DA_ItemData
Name: DA_Item_MedKit
```
### 1.2 — Fill Core Properties
| Property | Value | Notes |
|----------|-------|-------|
| `Item Tag` | `Framework.Item.Consumable.MedKit` | Unique identity |
| `Display Name` | "MedKit" | Player sees this |
| `Description` | "A standard medical kit. Restores 25 health." | Shown in inventory |
| `Icon` | `T_MedKit_Icon` | Any red/white cross texture for prototype |
| `World Mesh` | `SM_MedKit` | Soft reference — Construction Script resolves it |
| `Weight` | `1.0` | Light carry weight |
| `Stack Limit` | `5` | Can carry up to 5 in one stack |
| `Item Type` | `Consumable` | Triggers Consumable Data panel |
### 1.3 — Fill Consumable Data
When `ItemType == Consumable`, the `Consumable Data` panel appears:
| Field | Value | Notes |
|-------|-------|-------|
| `Health Restore` | `25.0` | How much HP to restore (0-100 clamp) |
| `Stress Reduce` | `0.0` | Optional stress relief |
| `Use Duration` | `2.0` | Seconds to consume (animation time) |
| `bConsumedOnUse` | ✓ (true) | Item is removed from inventory after use |
### 1.4 — Save
The Data Asset is ready. No other config needed for a simple consumable.
---
## 2. Create the BP_Pickup_MedKit
Follow the same pattern as the flashlight pickup, but simpler — no active-use actor needed.
### 2.1 — Create Blueprint
```
Content Browser → Game/Pickups/
Right-click → Blueprint Class → Actor
Name: BP_Pickup_MedKit
```
### 2.2 — Add Components
| # | Component | Name | Purpose |
|---|-----------|------|---------|
| 1 | `StaticMeshComponent` | `Mesh` | Renders the medkit model |
| 2 | `SphereComponent` | `PickupTrigger` | Interaction radius (Sphere Radius → 150) |
Select `PickupTrigger` → Details → Collision Presets → `OverlapOnlyPawn`
### 2.3 — Create ItemData Variable
**+ Variable** → Name: `ItemData` → Type: `DA_ItemData → Object Reference`
Select the variable → Details:
- **Instance Editable** → ✓
- **Category** → `Pickup`
### 2.4 — Wire Construction Script
```
[Construction Script]
├─ ItemData → Is Valid? → Branch
│ ├─ True:
│ │ ├─ ItemData → Get World Mesh → Load Synchronous → Set Static Mesh (Mesh)
│ │ └─ ItemData → Get Display Name → Set Actor Label
│ └─ False:
│ └─ Print String ("No ItemData assigned to BP_Pickup_MedKit")
```
### 2.5 — Add I_Interactable and Wire
Same pattern as flashlight. The key difference for consumables is **stacking**: the pickup can hold multiple units.
```
Event Interact
│ Interactor: AActor*
├─ Interactor → Get Component by Class (UBPC_InventorySystem) → Is Valid?
│ │
│ └─ True → [Inventory]
│ │
│ ├─ Can Add Item(ItemData, Quantity=1)
│ │ │
│ │ ├─ True → Add Item(ItemData, Quantity=1) → Destroy Actor → Return True
│ │ │
│ │ └─ False:
│ │ ├─ Print "Inventory Full"
│ │ └─ Return False
```
> For multi-pickup stacks (e.g., picking up 3 medkits at once), set a `Quantity` variable (Integer, Instance Editable) and pass it to `Add Item`. The inventory auto-stacks identical items.
### 2.6 — Add Bobbing (optional)
Add a Timeline to `Event BeginPlay` with a sine wave for Z offset — same as flashlight example.
---
## 3. Wire Consumable Use (On Player Pawn)
When the player uses a consumable from their inventory or quick-slot:
### 3.1 — In BPC_ConsumableSystem (BP child on pawn)
```
Event Use Consumable (custom event)
│ ItemData: DA_ItemData*
├─ ItemData → Get Consumable Data (Break FItemConsumableData)
│ │
│ ├─ Health Restore > 0?
│ │ └─ True:
│ │ ├─ Get Owner → Get Component by Class (UBPC_HealthSystem)
│ │ │ │
│ │ │ └─ Is Valid? → True:
│ │ │ └─ Apply Healing (HealthRestore, Healer=self)
│ │ │ │
│ │ │ └─ Print String: "Restored {HealthRestore} HP"
│ │ │
│ │ └─ False: Print "No HealthSystem found"
│ │
│ ├─ Stress Reduce > 0?
│ │ └─ True:
│ │ └─ Get BPC_StressSystem → Remove Stress (StressReduce)
│ │
│ ├─ bConsumedOnUse?
│ │ └─ True:
│ │ └─ Get BPC_InventorySystem → Remove Item (ItemData, 1)
│ │
│ └─ (Optional) Play sound, screen effect, widget animation
```
### 3.2 — Quick Test Without Full Integration
Bind a test key (e.g., `IA_UseItem`) in your player character:
```
Event InputAction (IA_UseItem, Pressed)
├─ Get Component by Class (UBPC_InventorySystem)
├─ Get All Items → For Each Loop
│ │
│ ├─ Break FInventorySlot → Item
│ ├─ Item → Get Item Type == Consumable?
│ │ └─ True:
│ │ ├─ Item → Get Consumable Data → Health Restore
│ │ ├─ Get BPC_HealthSystem → Apply Healing (HealthRestore)
│ │ ├─ Inventory → Remove Item (Item, 1)
│ │ └─ Break (exit loop — only use one)
│ │
│ └─ Continue loop
```
---
## 4. Verification Checklist
- [ ] **Data Asset:** `DA_Item_MedKit` has `ItemType = Consumable`, `HealthRestore = 25`, `StackLimit = 5`
- [ ] **Pickup in level:** Mesh appears, bobs, interaction prompt shows "Pick up MedKit"
- [ ] **Inventory:** Pick up medkit → appears in inventory slot. Pick up 4 more → they stack (quantity = 5). Pick up 6th → fails (stack limit).
- [ ] **Use:** Press use item key → health increases by 25, stack count decreases by 1
- [ ] **Weight:** Each medkit adds 1.0 to carry weight. `Get Remaining Weight` decreases by 1.0 per pickup.
- [ ] **Full inventory:** Pick up medkit when no slots left → "Inventory Full" feedback, pickup remains in world
---
## 5. Key Concepts
| Concept | How It Works |
|---------|-------------|
| **Stacking** | `StackLimit = 5` on the Data Asset. `BPC_InventorySystem.AddItem()` auto-finds existing stacks and adds to them instead of creating new slots. |
| **Consumed on use** | `bConsumedOnUse = true``BPC_ConsumableSystem` calls `RemoveItem()` after applying effects. Set to `false` for reusable items (e.g., a reusable syringe with cooldown). |
| **Soft references** | `WorldMesh` is a `TSoftObjectPtr<UStaticMesh>` — it doesn't load into memory until Construction Script resolves it. This keeps memory low when assets aren't in use. |
| **Inventory weight** | `BPC_InventorySystem.CurrentWeight` auto-updates when items are added/removed. `CanAddItem()` checks weight capacity before pickup. |