- 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.
9.0 KiB
9.0 KiB
BP_PuzzleDeviceActor — Puzzle Device Actor
Parent Class: Actor
Category: Interaction
Target UE Version: 5.5–5.7
Build Phase: 2 — Interaction
1. Overview
BP_PuzzleDeviceActor is the base actor for all puzzle devices in the world — levers, pressure plates, valve wheels, keypads, combination locks, circuit boards, and custom logic puzzles. Each instance references a DA_PuzzleData that defines the puzzle rules, solution, and completion effects.
2. Enums
E_PuzzleType
| Value | Description |
|---|---|
Lever |
Single or multi-lever sequence |
PressurePlate |
Weight-activated plate |
ValveWheel |
Rotate-to-open valve |
Keypad |
Numeric code entry |
CombinationLock |
Multi-dial combination |
CircuitBoard |
Connect-the-pins puzzle |
Custom |
Script-driven puzzle |
E_PuzzleState
| Value | Description |
|---|---|
Unsolved |
Puzzle not yet completed |
InProgress |
Player interacting with puzzle |
Solved |
Puzzle completed successfully |
Failed |
Puzzle failed (if retryable) |
Locked |
Puzzle locked (requires item/flag) |
3. Variables
| Variable | Type | Description |
|---|---|---|
PuzzleData |
DA_PuzzleData* |
Data asset defining this puzzle |
CurrentState |
E_PuzzleState |
Current puzzle state |
bIsInteractable |
bool |
Can player interact with this puzzle |
InteractionPrompt |
FText |
Prompt text for interaction |
LinkedActor |
AActor* |
Actor to notify on solve (door, gate, etc.) |
bResetOnFail |
bool |
Auto-reset after failure |
MaxAttempts |
int32 |
Max attempts before lockout (-1 = unlimited) |
CurrentAttempts |
int32 |
Attempts used so far |
CooldownSeconds |
float |
Time before re-interaction allowed |
4. Functions
| Function | Description |
|---|---|
BeginInteraction |
Player starts interacting with puzzle |
EndInteraction |
Player exits puzzle UI |
CheckSolution |
Validates player input against puzzle data |
OnPuzzleSolved |
Processes completion — notifies LinkedActor |
OnPuzzleFailed |
Processes failure — resets or locks |
ResetPuzzle |
Resets puzzle to default state |
GetPuzzleState |
Returns current E_PuzzleState |
5. Event Dispatchers
| Dispatcher | Payload | Description |
|---|---|---|
OnPuzzleStateChanged |
E_PuzzleState NewState |
State transition occurred |
OnPuzzleSolved |
AActor* Solver |
Puzzle completed |
OnPuzzleFailed |
int32 AttemptNumber |
Attempt failed |
OnPuzzleLinkedActorTriggered |
AActor* LinkedActor |
Linked actor notified |
6. Dependencies & Communication
| System | Relationship |
|---|---|
DA_PuzzleData |
Defines puzzle rules and solution |
BPC_InteractionDetector |
Focus and interaction initiation |
BP_DoorActor |
Common linked actor (unlock on solve) |
BPC_NarrativeStateSystem |
Set narrative flags on solve |
SS_SaveManager |
Persist puzzle state |
7. Reuse Notes
- All puzzle logic is data-driven via
DA_PuzzleData - LinkedActor pattern decouples puzzle from effect
8. Manual Implementation Guide
8.1 Class Setup
- Create Blueprint Class: Parent =
Actor, Name =BP_PuzzleDeviceActor - Add components: StaticMesh (visual), InteractionCollision (Sphere), WidgetComponent (for interaction prompt)
- Implement Interfaces:
I_Interactable - 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