# BPC_KeyItemSystem — Key Item System **Parent Class:** `ActorComponent` **Category:** Inventory **Target UE Version:** 5.5–5.7 **Build Phase:** 3 — Inventory ## 1. Overview `BPC_KeyItemSystem` manages key items — story-critical objects that unlock doors, trigger narrative events, or are required for puzzle completion. Tracks acquired keys, provides query for door/puzzle unlock checks, and supports key usage notifications. ## 2. Variables | Variable | Type | Description | |----------|------|-------------| | `AcquiredKeys` | `TArray` | Tags of all acquired key items | | `bShowKeyNotifications` | `bool` | Toast on key pickup | | `KeyItemCategory` | `E_ItemCategory` | KeyItem category filter | ## 3. Functions | Function | Description | |----------|-------------| | `HasKey` | Checks if player has a specific key by tag | | `AddKey` | Registers a key item acquisition | | `RemoveKey` | Removes a key (if consumed) | | `GetAllKeys` | Returns all acquired key tags | | `CanUnlock` | Checks if player meets unlock requirements for a target | ## 4. Event Dispatchers | Dispatcher | Payload | Description | |------------|---------|-------------| | `OnKeyAcquired` | `FGameplayTag KeyTag` | New key picked up | | `OnKeyUsed` | `FGameplayTag KeyTag`, `AActor* Target` | Key used on target | | `OnKeyRemoved` | `FGameplayTag KeyTag` | Key consumed/removed | ## 5. Dependencies | System | Relationship | |--------|--------------| | `BPC_InventorySystem` | Keys as inventory items | | `BP_DoorActor` | Door unlock queries | | `BP_PuzzleDeviceActor` | Puzzle unlock gates | | `BPC_NarrativeStateSystem` | Key-based narrative flags | ## 6. Reuse Notes - Keys use gameplay tags for generic matching (any key with same tag works) - Supports consumable keys (removed after single use) and persistent keys --- ## 7. Manual Implementation Guide ### 7.1 Class Setup 1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_KeyItemSystem` 2. Add to Player Character 3. Keys are inventory items with `ItemType = KeyItem` and `bIsKeyItem = true` in DA_ItemData. ### 7.2 Variable Initialization (BeginPlay) ``` Event BeginPlay ├─ Set AcquiredKeys = empty Array ├─ Set bShowKeyNotifications = true ├─ Get Owner → Find Component by Class (BPC_InventorySystem) → Cache │ └─ Bind to OnItemAdded → OnItemAddedHandler └─ Bind to OnItemRemoved → OnItemRemovedHandler ``` ### 7.3 Function Implementations #### `HasKey(KeyTag: GameplayTag)` → `Boolean` ``` [Function: HasKey] (Pure) Step 1: ForEach AcquiredKeys: If AcquiredKeys[i].MatchesTag(KeyTag) → Return true Step 2: Optionally check inventory directly: Get InventorySystem → Call FindItemByTag(KeyTag) If found → Return true Step 3: Return false ``` **Nodes:** `ForEachLoop`, `Matches Tag`, `Branch`, `FindItemByTag` #### `AddKey(KeyTag: GameplayTag)` → `void` ``` [Function: AddKey] Step 1: Check if tag already in AcquiredKeys: ForEach → if MatchesTag(KeyTag) → Return (no duplicates) Step 2: Add KeyTag to AcquiredKeys array Step 3: If bShowKeyNotifications: Get WBP_HUDController → Create Notification Toast: "Key acquired: {GetTagDisplayName(KeyTag)}" Step 4: Fire OnKeyAcquired(KeyTag) ``` #### `RemoveKey(KeyTag: GameplayTag)` → `Boolean` ``` [Function: RemoveKey] Step 1: ForEach AcquiredKeys (iterate backwards): If AcquiredKeys[i].MatchesTag(KeyTag): Remove from array at index i Fire OnKeyRemoved(KeyTag) Return true Step 2: Return false (key not found) ``` #### `GetAllKeys()` → `Array` ``` [Function: GetAllKeys] (Pure) Step 1: Get BPC_InventorySystem → Call FindAllItemsByCategory(KeyItem) Step 2: Also include AcquiredKeys (permanent keys that were consumed) Step 3: Return combined unique list ``` #### `CanUnlock(Target: Actor)` → `Boolean, Text (failReason)` ``` [Function: CanUnlock] Step 1: Check if Target implements I_Lockable: DoesImplementInterface → If not, return (false, "Cannot be unlocked") Step 2: Get RequiredKeyTag from Target: Call I_Lockable.GetRequiredKeyTag(Target) → RequiredTag Step 3: Call HasKey(RequiredTag): True → Return (true, "") False → Return (false, "Requires: " + GetTagDisplayName(RequiredTag)) ``` #### `UseKeyOnTarget(KeyTag: GameplayTag, Target: Actor)` → `Boolean` ``` [Function: UseKeyOnTarget] Step 1: Verify HasKey(KeyTag) → If false, return false Step 2: Call CanUnlock(Target): If false → return false Step 3: Check if Target has I_Lockable.TryUnlock: Call I_Lockable.TryUnlock(Target, KeyTag) → bSuccess Step 4: If bSuccess: Fire OnKeyUsed(KeyTag, Target) Step 5: Check if key should be consumed: Get InventorySystem → FindItemByTag(KeyTag) If ItemData.bConsumeOnUse: Call RemoveKey(KeyTag) Get InventorySystem → RemoveItemByTag(KeyTag, 1) Step 6: Return bSuccess ``` ### 7.4 Event Dispatcher Bindings | Bind to Dispatcher | Custom Event | Logic | |-------------------|-------------|-------| | `BPC_InventorySystem.OnItemAdded(Item)` | `OnItemAddedHandler` | If Item.ItemData.ItemType == KeyItem → Call AddKey(Item.ItemData.ItemTag) | | `BPC_InventorySystem.OnItemRemoved(Item)` | `OnItemRemovedHandler` | If Item.ItemData.ItemType == KeyItem → Call RemoveKey(Item.ItemData.ItemTag) | ### 7.5 Blueprint Build Checklist - [ ] Create BPC_KeyItemSystem, add to Player Character - [ ] Add variables: AcquiredKeys (Array), bShowKeyNotifications, KeyItemCategory - [ ] Implement HasKey with tag matching and inventory fallback - [ ] Implement AddKey/RemoveKey with duplicate prevention - [ ] Implement CanUnlock using I_Lockable interface - [ ] Implement UseKeyOnTarget with consume-on-use check - [ ] Bind to BPC_InventorySystem.OnItemAdded/OnItemRemoved - [ ] Test: pick up key → attempt locked door → unlock succeeds → key consumed