feat: Enhance interaction and inventory systems with new components and functionality
- Added BPC_UsableWorldObjectSystem for handling various interactable world objects with detailed manual implementation guide. - Introduced BPC_ActiveItemSystem to manage quick slots and active item usage, including cycling and selection logic. - Implemented BPC_DocumentArchiveSystem for managing collectible documents with read tracking and categorization. - Developed BPC_JournalSystem for narrative entries with auto-adding features based on gameplay events. - Created BPC_KeyItemSystem for key management with consumable and persistent key support. - Enhanced BPC_FirearmSystem for ranged weapon mechanics, including hitscan and projectile firing. - Updated BPC_MeleeSystem for melee combat with combo and blocking mechanics. - Established BPC_ReloadSystem for managing weapon reloading processes, including partial reloads and state management.
This commit is contained in:
@@ -94,4 +94,167 @@
|
||||
|
||||
## 7. Reuse Notes
|
||||
- All puzzle logic is data-driven via `DA_PuzzleData`
|
||||
- LinkedActor pattern decouples puzzle from effect
|
||||
- LinkedActor pattern decouples puzzle from effect
|
||||
|
||||
---
|
||||
|
||||
## 8. Manual Implementation Guide
|
||||
|
||||
### 8.1 Class Setup
|
||||
1. Create Blueprint Class: Parent = `Actor`, Name = `BP_PuzzleDeviceActor`
|
||||
2. Add components: StaticMesh (visual), InteractionCollision (Sphere), WidgetComponent (for interaction prompt)
|
||||
3. Implement Interfaces: `I_Interactable`
|
||||
4. Save to: `Content/Framework/Interaction/`
|
||||
|
||||
### 8.2 Variable Initialization (BeginPlay / Construction Script)
|
||||
```
|
||||
Event BeginPlay
|
||||
├─ Set CurrentState = Unsolved (or Locked if requires unlock first)
|
||||
├─ Set CurrentAttempts = 0
|
||||
├─ Load PuzzleData → if valid:
|
||||
│ ├─ Set InteractionPrompt = PuzzleData.PromptText
|
||||
│ ├─ Set MaxAttempts = PuzzleData.MaxAttempts
|
||||
│ ├─ Set CooldownSeconds = PuzzleData.Cooldown
|
||||
│ └─ Apply initial visual state (dim if locked, glowing if interactable)
|
||||
└─ Register with SS_SaveManager if implements I_Persistable
|
||||
```
|
||||
|
||||
### 8.3 Function Implementations
|
||||
|
||||
#### `I_Interactable: OnInteract(Instigator: Actor)` → `Boolean`
|
||||
|
||||
```
|
||||
[Function: OnInteract] — called by BPC_InteractionDetector
|
||||
Step 1: Branch on CurrentState:
|
||||
Case Unsolved → Call BeginInteraction(Instigator) → Return true
|
||||
Case Solved → Play solved animation/sound → Return false (already solved)
|
||||
Case Locked → Check if Instigator has required key:
|
||||
If yes → unlock → BeginInteraction
|
||||
If no → Play locked feedback → Return false
|
||||
Case InProgress → Return false (already interacting)
|
||||
Case Failed → If bResetOnFail: ResetPuzzle → BeginInteraction
|
||||
```
|
||||
|
||||
#### `BeginInteraction(Instigator: Actor)` → `void`
|
||||
|
||||
```
|
||||
[Function: BeginInteraction]
|
||||
Step 1: Set CurrentState = InProgress
|
||||
Step 2: Set bIsInteractable = false (block re-interaction during solve)
|
||||
Step 3: Fire OnPuzzleStateChanged(InProgress)
|
||||
|
||||
Step 4: Branch on PuzzleData.PuzzleType:
|
||||
Lever, PressurePlate, ValveWheel:
|
||||
- No UI overlay needed; player manipulates world objects
|
||||
- Enable input on the puzzle's interactive levers/buttons
|
||||
Keypad, CombinationLock, CircuitBoard:
|
||||
- Open puzzle UI widget (attached to WidgetComponent or fullscreen)
|
||||
- Set player input mode to UI Only
|
||||
- Route input to puzzle widget
|
||||
|
||||
Step 5: Block player movement (optional, per puzzle config)
|
||||
Step 6: Set interaction camera view (zoom to puzzle if needed)
|
||||
```
|
||||
|
||||
#### `CheckSolution(PlayerInput: varies by puzzle type)` → `Boolean`
|
||||
|
||||
```
|
||||
[Function: CheckSolution]
|
||||
Step 1: Read correct solution from PuzzleData.Solution
|
||||
Step 2: Compare player input against solution:
|
||||
- Lever sequence: check order of pulled levers matches solution
|
||||
- Keypad: check entered code matches solution code
|
||||
- CombinationLock: check each dial position
|
||||
- CircuitBoard: check all connections match solution
|
||||
- PressurePlate: check weight/actor matches
|
||||
Step 3: If match:
|
||||
Call OnPuzzleSolved(Instigator)
|
||||
Return true
|
||||
Step 4: If no match:
|
||||
Increment CurrentAttempts
|
||||
Branch on MaxAttempts != -1 AND CurrentAttempts >= MaxAttempts:
|
||||
True → Call OnPuzzleFailed()
|
||||
False → Show hint/wrong feedback, allow retry
|
||||
Return false
|
||||
```
|
||||
|
||||
**Node example for keypad puzzle:**
|
||||
```
|
||||
Get SolutionString from PuzzleData
|
||||
Branch: PlayerInputCode == SolutionString
|
||||
```
|
||||
|
||||
#### `OnPuzzleSolved(Solver: Actor)` → `void`
|
||||
|
||||
```
|
||||
[Function: OnPuzzleSolved]
|
||||
Step 1: Set CurrentState = Solved
|
||||
Step 2: Set bIsInteractable = false (permanently)
|
||||
Step 3: Play solved visual: change material to green/solved glow
|
||||
Step 4: Play solved sound via SS_AudioManager
|
||||
Step 5: Fire OnPuzzleSolved(Solver)
|
||||
Step 6: Fire OnPuzzleStateChanged(Solved)
|
||||
|
||||
Step 7: Notify LinkedActor (if set):
|
||||
If LinkedActor valid:
|
||||
If LinkedActor implements I_Toggleable → Call Toggle(Solver)
|
||||
If LinkedActor implements I_Lockable → Call Unlock(Solver)
|
||||
Fire OnPuzzleLinkedActorTriggered(LinkedActor)
|
||||
|
||||
Step 8: Grant rewards from PuzzleData:
|
||||
Get BPC_InventorySystem → If PuzzleData.RewardItem valid → Call AddItem
|
||||
Get BPC_NarrativeStateSystem → Set flag: PuzzleData.CompletionFlag
|
||||
|
||||
Step 9: EndInteraction()
|
||||
```
|
||||
|
||||
#### `OnPuzzleFailed()` → `void`
|
||||
|
||||
```
|
||||
[Function: OnPuzzleFailed]
|
||||
Step 1: Set CurrentState = Failed
|
||||
Step 2: Play failure sound/visual
|
||||
Step 3: Fire OnPuzzleFailed(CurrentAttempts)
|
||||
Step 4: Fire OnPuzzleStateChanged(Failed)
|
||||
|
||||
Step 5: Branch on bResetOnFail:
|
||||
True → Start timer for CooldownSeconds → Call ResetPuzzle
|
||||
False → If MaxAttempts reached: Set CurrentState = Locked permanently
|
||||
|
||||
Step 6: EndInteraction()
|
||||
```
|
||||
|
||||
#### `EndInteraction()` → `void`
|
||||
|
||||
```
|
||||
[Function: EndInteraction]
|
||||
Step 1: Close puzzle UI widget (if open)
|
||||
Step 2: Restore player input mode to Game Only
|
||||
Step 3: Re-enable player movement
|
||||
Step 4: Restore camera to default
|
||||
Step 5: If CurrentState != InProgress → Set bIsInteractable = true
|
||||
```
|
||||
|
||||
#### `ResetPuzzle()` → `void`
|
||||
|
||||
```
|
||||
[Function: ResetPuzzle]
|
||||
Step 1: Set CurrentState = Unsolved
|
||||
Step 2: Set CurrentAttempts = 0
|
||||
Step 3: Reset all puzzle levers/dials/inputs to default positions
|
||||
Step 4: Set bIsInteractable = true
|
||||
Step 5: Fire OnPuzzleStateChanged(Unsolved)
|
||||
```
|
||||
|
||||
### 8.4 Blueprint Build Checklist
|
||||
- [ ] Create BP_PuzzleDeviceActor actor with mesh + collision + widget components
|
||||
- [ ] Implement I_Interactable interface
|
||||
- [ ] Add all variables: PuzzleData, CurrentState, bIsInteractable, LinkedActor, MaxAttempts, etc.
|
||||
- [ ] Implement BeginInteraction with type-switch (lever vs UI vs custom)
|
||||
- [ ] Implement CheckSolution with type-specific validation
|
||||
- [ ] Implement OnPuzzleSolved (visual, sound, LinkedActor, rewards, narrative flag)
|
||||
- [ ] Implement OnPuzzleFailed (retry or lockout)
|
||||
- [ ] Implement EndInteraction (UI close, input restore, camera restore)
|
||||
- [ ] Implement ResetPuzzle for retryable puzzles
|
||||
- [ ] Bind to BPC_InteractionDetector via I_Interactable
|
||||
- [ ] Test: approach puzzle → interact → solve → door unlocks → save/load restores state
|
||||
Reference in New Issue
Block a user