Files
Lefteris Notas eeb1bf82c9 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.
2026-05-19 18:37:42 +03:00

9.0 KiB
Raw Permalink Blame History

BP_PuzzleDeviceActor — Puzzle Device Actor

Parent Class: Actor Category: Interaction Target UE Version: 5.55.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

  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