# BPC_ActiveItemSystem — Active Item System

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

---

## 1. Overview

`BPC_ActiveItemSystem` manages the player's currently selected/active item and quick slot assignments. It reads from [`BPC_InventorySystem`](BPC_InventorySystem.md) and maps up to 8 quick slots to inventory items, handling hotkey input, item switching, and active item context (usable, throwable, consumable).

---

## 2. Enums

### `E_QuickSlot`

| Value | Description |
|-------|-------------|
| `Slot_1` | Hotkey 1 |
| `Slot_2` | Hotkey 2 |
| `Slot_3` | Hotkey 3 |
| `Slot_4` | Hotkey 4 |
| `Slot_5` | Hotkey 5 |
| `Slot_6` | Hotkey 6 |
| `Slot_7` | Hotkey 7 |
| `Slot_8` | Hotkey 8 |

---

## 3. Variables

| Variable | Type | Description |
|----------|------|-------------|
| `QuickSlots` | `TMap<E_QuickSlot, FGuid>` | Hotkey → Inventory Item ID mapping |
| `ActiveSlot` | `E_QuickSlot` | Currently selected quick slot |
| `ActiveItem` | `S_InventoryEntry` | Currently active item data |
| `bHasActiveItem` | `bool` | An item is currently selected |
| `bCanSwitchItems` | `bool` | Item switching allowed (not during anim) |
| `SwitchCooldown` | `float` | Min time between item switches |

---

## 4. Functions

| Function | Description |
|----------|-------------|
| `SetQuickSlot` | Assigns an inventory item to a quick slot |
| `ClearQuickSlot` | Clears a quick slot assignment |
| `SelectSlot` | Sets the active quick slot by key press |
| `GetActiveItem` | Returns current `S_InventoryEntry` |
| `UseActiveItem` | Uses/consumes the active item |
| `CycleNextItem` | Selects the next populated quick slot |
| `CyclePreviousItem` | Selects the previous populated quick slot |
| `IsQuickSlotEmpty` | Returns true if quick slot has no item |
| `GetQuickSlotItem` | Returns item in a specific quick slot |

---

## 5. Event Dispatchers

| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnActiveItemChanged` | `S_InventoryEntry NewItem`, `E_QuickSlot Slot` | Active item switched |
| `OnQuickSlotAssigned` | `E_QuickSlot Slot`, `FGuid ItemID` | Item assigned to quick slot |
| `OnQuickSlotCleared` | `E_QuickSlot Slot` | Quick slot cleared |
| `OnActiveItemUsed` | `S_InventoryEntry Item` | Active item consumed |

---

## 6. Dependencies & Communication

| System | Relationship |
|--------|--------------|
| `BPC_InventorySystem` | Reads inventory slots; source of truth for items |
| `BPC_EquipmentSlotSystem` | Automatically updates quick slots on equipment change |
| `WBP_HUDController` | Displays active item in HUD |
| `BPC_HealthSystem` | Consumed health items trigger healing |

---

## 7. Reuse Notes
- Quick slots are configurable per project (4-8 slots)
- Active item system is the bridge between inventory data and gameplay input

---

## 8. Manual Implementation Guide

### 8.1 Class Setup
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_ActiveItemSystem`
2. Add to Player Character
3. Quick slots map inventory ItemIDs (Guid) to hotkey numbers (1-8)

### 8.2 Variable Initialization (BeginPlay)
```
Event BeginPlay
  ├─ Set QuickSlots = empty Map<E_QuickSlot, Guid>
  ├─ Set ActiveSlot = Slot_1
  ├─ Set ActiveItem = empty S_InventoryEntry
  ├─ Set bHasActiveItem = false
  ├─ Set bCanSwitchItems = true
  ├─ Set SwitchCooldown = 0.2
  └─ Get Owner → Find Component by Class (BPC_InventorySystem) → Cache
       └─ Bind to OnInventoryChanged → RefreshActiveItem
```

### 8.3 Function Implementations

#### `SetQuickSlot(Slot: E_QuickSlot, ItemID: Guid)` → `void`

```
[Function: SetQuickSlot]
  Step 1: Add/Update QuickSlots map: QuickSlots.Add(Slot, ItemID)
  Step 2: If ActiveSlot == Slot → Refresh active item display
  Step 3: Fire OnQuickSlotAssigned(Slot, ItemID)
```

#### `ClearQuickSlot(Slot: E_QuickSlot)` → `void`

```
[Function: ClearQuickSlot]
  Step 1: QuickSlots.Remove(Slot)
  Step 2: If ActiveSlot == Slot:
    Set bHasActiveItem = false, ActiveItem = empty
    Fire OnActiveItemChanged(empty, Slot)
  Step 3: Fire OnQuickSlotCleared(Slot)
```

#### `SelectSlot(Slot: E_QuickSlot)` → `void`

```
[Function: SelectSlot]
  Step 1: Branch on bCanSwitchItems → If false, return (switching blocked during animation)
  Step 2: Get ItemID from QuickSlots[Slot] → if no entry, return
  Step 3: Get InventorySystem → Call GetItemById(ItemID)
  Step 4: If item found AND valid:
    Set ActiveSlot = Slot
    Set ActiveItem = found entry
    Set bHasActiveItem = true
    Fire OnActiveItemChanged(ActiveItem, Slot)
  Step 5: If item NOT found (was removed from inventory):
    Call ClearQuickSlot(Slot) — auto-clean stale slot
```

**Nodes:** `Map Find`, `GetItemById`, `Branch IsValid`, `Fire Event`

#### `GetActiveItem()` → `S_InventoryEntry` *(Pure)*

```
[Function: GetActiveItem]
  Return ActiveItem
```

#### `UseActiveItem()` → `Boolean`

```
[Function: UseActiveItem]
  Step 1: Branch on bHasActiveItem → If false, return false
  Step 2: Get InventorySystem → Call UseItem(ActiveItem.SlotIndex)
  Step 3: Branch on result == Success:
    True → Fire OnActiveItemUsed(ActiveItem) → Return true
    False → Return false (item not usable, cooldown, etc.)
```

#### `CycleNextItem()` → `void`

```
[Function: CycleNextItem]
  Step 1: CurrentIndex = ActiveSlot (as int, 1-8)
  Step 2: Loop 8 times:
    NextIndex = (CurrentIndex + i) % 8 + 1
    If NOT IsQuickSlotEmpty(NextIndex):
      Call SelectSlot(NextIndex)
      Return
  Step 3: No populated slots → do nothing
```

#### `CyclePreviousItem()` → `void`

```
[Function: CyclePreviousItem]
  Same as CycleNextItem but decrementing: NextIndex = (CurrentIndex - i + 7) % 8 + 1
```

#### `IsQuickSlotEmpty(Slot: E_QuickSlot)` → `Boolean`

```
[Function: IsQuickSlotEmpty]
  If QuickSlots.Find(Slot) returns valid → Return false
  Return true
```

#### `RefreshActiveItem()` → `void` *(Called when inventory changes)*

```
[Function: RefreshActiveItem]
  Step 1: If NOT bHasActiveItem → Return
  Step 2: Get InventorySystem → GetItemAtSlot(ActiveItem.SlotIndex)
  Step 3: If item still exists AND same ItemID:
    Update ActiveItem (stack count may have changed)
    Fire OnActiveItemChanged(ActiveItem, ActiveSlot)
  Step 4: If item no longer exists:
    Set bHasActiveItem = false, ActiveItem = empty
    ClearQuickSlot(ActiveSlot)
```

### 8.4 Event Dispatcher Bindings
| Bind to Dispatcher | Custom Event | Logic |
|-------------------|-------------|-------|
| `BPC_InventorySystem.OnInventoryChanged` | `RefreshActiveItem` | Re-validate current active item exists |
| `InputAction IA_Hotkey1` through `IA_Hotkey8` | `OnHotkeyPressed(Slot)` | Call SelectSlot corresponding slot |
| `InputAction IA_NextItem` | `OnNextItem` | Call CycleNextItem |
| `InputAction IA_PreviousItem` | `OnPreviousItem` | Call CyclePreviousItem |
| `InputAction IA_UseItem` | `OnUseItem` | Call UseActiveItem |

### 8.5 Blueprint Build Checklist
- [ ] Define E_QuickSlot enum (Slot_1 through Slot_8)
- [ ] Create BPC_ActiveItemSystem, add to Player Character
- [ ] Add variables: QuickSlots (Map), ActiveSlot, ActiveItem, bHasActiveItem, bCanSwitchItems, SwitchCooldown
- [ ] Implement SetQuickSlot/ClearQuickSlot for assignment
- [ ] Implement SelectSlot with validity check and stale cleanup
- [ ] Implement UseActiveItem routing to InventorySystem.UseItem
- [ ] Implement CycleNext/Previous with wrap-around
- [ ] Create 8 Input Actions: IA_Hotkey1 through IA_Hotkey8
- [ ] Bind hotkey inputs + next/previous item cycling
- [ ] Bind to OnInventoryChanged for auto-refresh
- [ ] Test: assign item to slot 1 → press 1 to select → press Use to consume