# BPC_UsableWorldObjectSystem — Usable World Object System

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

## 1. Overview
`BPC_UsableWorldObjectSystem` powers generic usable objects in the world — switches, buttons, valves, terminals, readable notes, audio logs. Provides a unified interaction interface for any object the player can "use" via the InteractionDetector.

## 2. Enums
### `E_UsableObjectType`
| Value | Description |
|-------|-------------|
| `Switch` | Toggleable switch |
| `Button` | Pressable button |
| `Valve` | Rotatable valve |
| `Terminal` | Interactive screen |
| `Readable` | Note/book |
| `AudioLog` | Audio playback device |
| `Generic` | Custom interaction |

## 3. Variables
| Variable | Type | Description |
|----------|------|-------------|
| `ObjectType` | `E_UsableObjectType` | Type of usable object |
| `InteractionData` | `DA_InteractionData*` | Interaction definition |
| `bIsActive` | `bool` | Object enabled |
| `bSingleUse` | `bool` | Can only be used once |
| `bHasBeenUsed` | `bool` | Tracked if single-use |
| `CooldownSeconds` | `float` | Reuse cooldown |

## 4. Functions
| Function | Description |
|----------|-------------|
| `OnUse` | Executes interaction logic |
| `SetEnabled` | Enable/disable object |
| `ResetObject` | Return to initial state |

## 5. Event Dispatchers
| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnObjectUsed` | `AActor* User` | Object successfully used |
| `OnObjectStateChanged` | `bool bIsActive` | State toggled |

## 6. Dependencies
| System | Relationship |
|--------|--------------|
| `BPC_InteractionDetector` | Focus and interaction routing |
| `DA_InteractionData` | Data-driven interaction config |

## 7. Reuse Notes
- Generic base for all "press E to use" world objects
- Can be subclassed for specialized behavior

---

## 8. Manual Implementation Guide

### 8.1 Class Setup
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_UsableWorldObjectSystem`
2. Attach to any world actor that should be "usable" (switches, buttons, valves, terminals, notes, audio logs)
3. The owner actor must implement `I_Interactable` (or this component implements it on behalf of owner)

### 8.2 Variable Initialization (BeginPlay)
```
Event BeginPlay
  ├─ Set bIsActive = true
  ├─ Set bHasBeenUsed = false
  ├─ Load InteractionData (Data Asset reference)
  │    ├─ Read PromptText → store for UI
  │    ├─ Read InteractionDuration → for hold interactions
  │    └─ Read ObjectType → set behavior mode
  └─ Set LinkedActor from owner variable (designer-assigned in editor)
```

### 8.3 Function Implementations

#### `OnUse(Instigator: Actor)` → `Boolean`

```
[Function: OnUse] — core interaction handler

  Step 1: Branch on bIsActive → If false, Fire OnObjectStateChanged(false), Return false
  Step 2: Branch on bSingleUse AND bHasBeenUsed:
    True → Return false (already used once)

  Step 3: Switch on ObjectType:
    Case Switch:
      - Toggle bIsActive (invert)
      - Play switch animation: flip lever/button
      - If LinkedActor: call I_Toggleable.Toggle(Instigator) on LinkedActor
      - Start CooldownSeconds timer → bIsActive = true after cooldown

    Case Button:
      - Set bIsActive = false (press in)
      - Play button press animation
      - Notify LinkedActor if set
      - Start timer → spring back: bIsActive = true

    Case Valve:
      - Begin rotate interaction (player holds E and moves mouse)
      - Call Adjust on LinkedActor (I_Adjustable) with rotation delta
      - On release: stop adjustment

    Case Terminal:
      - Call OpenTerminal UI on LinkedActor or self
      - Set player input mode to UI Only
      - On close → restore input

    Case Readable:
      - Get NoteText from InteractionData
      - Call WBP_JournalDocumentViewer.OpenNote(NoteText)
      - Play "paper rustle" sound via SS_AudioManager

    Case AudioLog:
      - Get AudioClip from InteractionData
      - Call SS_AudioManager.PlayDialogue(AudioClip)
      - Show subtitle text if available

    Case Generic:
      - Fire custom dispatcher or call blueprint event OnGenericUse

  Step 4: Set bHasBeenUsed = true (if bSingleUse)
  Step 5: Fire OnObjectUsed(Instigator)
  Step 6: Return true
```

**Nodes:** `Switch on E_UsableObjectType`, `Play Animation`, `I_Toggleable.Toggle`, `Open UI Widget`, `Play Sound`

#### `SetEnabled(bEnabled: Boolean)` → `void`

```
[Function: SetEnabled]
  Step 1: Set bIsActive = bEnabled
  Step 2: Update visual: enable/disable highlight, change material
  Step 3: Fire OnObjectStateChanged(bEnabled)
```

#### `ResetObject()` → `void`

```
[Function: ResetObject]
  Step 1: Set bHasBeenUsed = false
  Step 2: Set bIsActive = true
  Step 3: Reset visual state to default
  Step 4: Fire OnObjectStateChanged(true)
```

### 8.4 I_Interactable Implementation (on owner actor)

If the component is on an actor that implements I_Interactable:

```
[Owner Actor: I_Interactable.OnInteract(Instigator)]
  Step 1: Get Component by Class (BPC_UsableWorldObjectSystem)
  Step 2: Call BPC_UsableWorldObjectSystem.OnUse(Instigator)

[Owner Actor: I_Interactable.CanInteract(Instigator)]
  Get UsableComp → Return UsableComp.bIsActive AND NOT (UsableComp.bSingleUse AND UsableComp.bHasBeenUsed)

[Owner Actor: I_Interactable.GetInteractionPrompt()]
  Get UsableComp → Return UsableComp.InteractionData.PromptText
```

### 8.5 Blueprint Build Checklist
- [ ] Define enum E_UsableObjectType and create DA_InteractionData with usage config
- [ ] Create BPC_UsableWorldObjectSystem component
- [ ] Add variables: ObjectType, InteractionData, bIsActive, bSingleUse, bHasBeenUsed, CooldownSeconds
- [ ] Implement OnUse with type-switch for all 7 object types
- [ ] Implement SetEnabled / ResetObject
- [ ] Create owner actor (BP_UsableObject) that implements I_Interactable
- [ ] Route I_Interactable calls to this component
- [ ] Set LinkedActor reference for Switch/Button objects
- [ ] Test: place switch → press E → linked light toggles → cooldown → press again