Add UI Overrides and Weapons Index documentation for Project Void

- Created ui-overrides.md detailing game-specific Widget Blueprint overrides, including purpose, widget index, visual styling, and accessibility requirements.
- Established weapons-index.md outlining all held weapon actors, including their components, logic, and comparisons for gameplay mechanics.
This commit is contained in:
Lefteris Notas
2026-05-21 22:27:57 +03:00
parent c515920eea
commit 040db37720
17 changed files with 6795 additions and 43 deletions

371
docs/game/enemies-index.md Normal file
View File

@@ -0,0 +1,371 @@
# Enemies Index — All Enemy Types
**Game:** Project Void | **Build Phase:** 12
**Framework Systems:** 80_BP_EnemyBase, 82_BPC_AlertSystem, 83_BPC_AIStateMachine, 84_AI_BaseAgentController, 85_BB_AgentBoard, 86_BPC_AIMemorySystem, 87_BPC_AIPerceptionSystem, 88_BPC_BehaviourVariantSelector
---
## Purpose
Defines the 3 enemy types, their AI controllers, behavior trees, blackboards, and integration with the horror framework systems. Plus the friendly NPC survivor.
---
## Enemy Catalog
| # | Enemy | Threat Level | Speed | Damage | Killable? | Vulnerability | Spawn Areas |
|---|-------|:---:|:---:|:---:|:---:|------|-------------|
| 1 | Patient | Medium | Slow (250) | 20 melee | YES | Light distracts briefly | Entry, WardA, WardB, Basement |
| 2 | Orderly | High | Fast (500) | 15 melee | YES | Flashlight blinds (slows 50%) | WardB, WardensOffice |
| 3 | Shade | Extreme | Teleport | 100 (1-hit) | NO | Light delays approach | WardB², Basement, VoidSpace |
² Shade appears once in WardB (scripted courtyard) + randomly in morgue
---
## 1. BP_Enemy_Patient — "The Lost"
**Parent:** `BP_EnemyBase` (80)
**Description:** Former asylum patients, twisted by the void. Slow but persistent. Walk with jerky, unnatural gait. Moan occasionally. Attack by grabbing and slashing.
### Components
| Component | Purpose |
|-----------|---------|
| `BP_EnemyBase` components (inherited) | Health (100), movement, skeletal mesh |
| `BPC_AlertSystem` (82) | Suspicious→Alerted→Combat |
| `BPC_AIStateMachine` (83) | Patrol/Search/Combat/Flee |
| `BPC_AIPerceptionSystem` (87) | Sight (120° cone, 2000u), Hearing (1500u) |
| `BPC_AIMemorySystem` (86) | Last known player location |
| `BPC_BehaviourVariantSelector` (88) | Aggressive/Curious/Erratic variants |
| `BPC_DamageReceptionSystem` (72) | Receive damage, hit reaction |
| `BPC_HitReactionSystem` (75) | Flinch/stagger on hit |
| `BPC_DeathCauseTracker` (73) | Log killing blow |
### AI Controller: AI_PatientController
**Parent:** `AI_BaseAgentController` (84)
```
Behavior Tree: BT_PatientBehavior
├─ Root → Selector
│ ├─ [Combat] Sequence
│ │ ├─ MoveTo (player last known location)
│ │ ├─ Wait (0.5s — "searching" animation)
│ │ ├─ MoveTo (player current location)
│ │ └─ Melee Attack → BPC_MeleeSystem.Swing
│ │
│ ├─ [Search] Sequence (unseen player, heard sound)
│ │ ├─ MoveTo (suspected location from BPC_AIMemorySystem)
│ │ ├─ Wait (2.0s — "sniffing" animation)
│ │ └─ Return to Patrol
│ │
│ └─ [Patrol] Sequence (default)
│ ├─ MoveTo (next waypoint on BP_PatrolPath_Asylum)
│ ├─ Wait (3-5s at each waypoint — random)
│ └─ Loop
```
### Blackboard: BB_PatientData
**Parent:** `BB_AgentBoard` (85)
| Key | Type | Purpose |
|-----|------|---------|
| `TargetActor` | Actor | Current target (player) |
| `LastKnownLocation` | Vector | From BPC_AIMemorySystem |
| `AlertState` | Enum | Calm/Suspicious/Alerted/Combat |
| `PatrolIndex` | Int | Current patrol waypoint |
| `bHasSeenPlayer` | Bool | Player was sighted |
| `bHeardSound` | Bool | Sound stimulus received |
| `SoundLocation` | Vector | Where sound came from |
### Perception
| Sense | Range | Angle | Notes |
|-------|:---:|:---:|-------|
| **Sight** | 2000u | 120° | Player flashlight increases detection range 50% |
| **Hearing** | 1500u | 360° | Running: detected at full range. Walking: 50%. Crouching: 25% |
| **Damage** | 3000u | 360° | Being shot alerts to player location instantly |
| **Touch** | 100u | 360° | Physical contact = immediate combat |
### Behaviour Variants (via DA_BehaviourVariant_Patient)
| Variant | Weight | Behavior |
|---------|:---:|----------|
| **Aggressive** | 40% | Charges directly, ignores hiding spots, attacks on sight |
| **Curious** | 35% | Approaches slowly, tilts head, investigates sounds first |
| **Erratic** | 25% | Randomly changes patrol path, sometimes stands still for 10s |
### Stress Impact on Player
- Patient visible: +3 stress/second
- Patient in combat: +5 stress/second
- Patient killed nearby: +10 stress (one-time spike)
---
## 2. BP_Enemy_Orderly — "The Wardens"
**Parent:** `BP_EnemyBase` (80)
**Description:** Former asylum staff. Fast, aggressive, but vulnerable to bright light. Walk with purposeful stride. Carry rusted medical tools as weapons.
### Key Differences from Patient
| Aspect | Patient | Orderly |
|--------|---------|---------|
| Speed | 250 (walk) | 500 (jog) |
| Health | 100 | 75 (weaker but faster) |
| Damage | 20 | 15 (faster attacks) |
| Attack Speed | 2.0s | 1.0s (rapid slashes) |
| Flashlight Effect | Distracts (looks away 2s) | Blinds (slows to 125 speed, misses attacks) |
| Hiding Detection | Can't detect hidden player | Can find hidden player if searched recently |
| Audio Cues | Moans, footsteps | Heavy breathing, keys jangling |
### Flashlight Vulnerability
```
Orderly enters player flashlight beam:
├─ BPC_AlertSystem.State == Combat?
│ ├─ True:
│ │ ├─ Set movement speed multiplier = 0.25 (slowed)
│ │ ├─ Set attack accuracy multiplier = 0.3 (misses often)
│ │ ├─ Play pained hiss sound
│ │ └─ After 5 seconds in light: Flee state (runs away)
│ │
│ └─ False:
│ ├─ Set AlertState = Suspicious
│ └─ Shield eyes animation, back away slowly
└─ Flashlight battery drains 2x faster when blinding an Orderly
```
### AI Controller: AI_OrderlyController
Same structure as Patient but with:
- Faster patrol (jog between waypoints)
- Hiding spot investigation behavior (checks lockers)
- Flashlight avoidance task (path around light beams)
---
## 3. BP_Enemy_Shade — "The Void"
**Parent:** `BP_EnemyBase` (80)
**Description:** The primary antagonist. A shifting, semi-corporeal entity from the void. Cannot be killed, only delayed. Teleports between dark areas. One-hit kills the player.
### Components
Same as Patient/Orderly PLUS:
| Component | Purpose |
|-----------|---------|
| `BPC_FearSystem` (90) | Generates fear aura (player stress +8/sec within 800u) |
| `Timeline "PhaseShift"` | Visual: model fades in/out when teleporting |
| `PointLightComponent "VoidGlow"` | Purple-black light aura (grows brighter when close) |
### Special Rules
| Rule | Behavior |
|------|----------|
| **Immortal** | Cannot be killed. Damage only delays (stuns for 3-5 seconds) |
| **Teleport** | Moves between dark areas (illuminance < 0.1). Cannot enter lit rooms |
| **Light Delayed** | Flashlight aimed at Shade slows approach speed 60% |
| **Sound Tracking** | FULL hearing range (5000u). Any sound = instant investigation |
| **One-Hit Kill** | Contact causes instant death Void Space |
| **Void Aura** | Radius 800u: player stress +8/sec, screen vignette darkens |
| **Persistence** | Remembers player across runs (session flag: "ShadeEncountered") |
| **Walls Don't Stop It** | Can phase through doors, walls (not during combat) |
### AI Controller: AI_ShadeController
```
Behavior Tree: BT_ShadeBehavior
├─ Root → Selector
│ ├─ [Void Hunt] Sequence (player detected by sound/sight)
│ │ ├─ Calculate "dark path" to player (avoid lit areas)
│ │ ├─ Teleport to next dark node (max 3000u per teleport)
│ │ ├─ Wait (1-3s — appears, stands still, watches)
│ │ ├─ MoveTo (player — floating, no walk animation)
│ │ ├─ On contact: KillPlayer → trigger void death
│ │ └─ If flashlight hits: Stun 3s, teleport away
│ │
│ └─ [Stalk] Sequence (default)
│ ├─ Teleport to dark location near player (800-1500u)
│ ├─ Wait (5-10s — watching)
│ ├─ SFX: whisper, breathing, or distant scream
│ └─ If player stays still > 10s: teleport closer
```
### Blackboard: BB_ShadeData
| Key | Type | Purpose |
|-----|------|---------|
| `TargetPlayer` | Actor | Player reference |
| `DarkNodes` | Array\<Vector\> | All dark locations in level (pre-calculated) |
| `CurrentDarkNode` | Vector | Current teleport position |
| `bIsStunned` | Bool | Recently hit by flashlight |
| `StunTimer` | Float | Remaining stun duration |
| `bHasKilledPlayer` | Bool | Killed player this encounter |
### Shade Encounter Design
| Location | Type | Trigger | Duration |
|----------|------|---------|----------|
| WardB Courtyard | **Scripted Teaser** | Player enters courtyard | 10s (watches then vanishes) |
| WardB Morgue | **Void Shift Guardian** | Void shift event | 30s (pursues during shift) |
| Basement | **Persistent Hunter** | Always active in basement | Entire level |
| Void Space | **Final Chase** | Enter void | Until exit or caught |
---
## 4. BP_NPC_Survivor (Friendly)
**Parent:** `Character`
**Description:** A surviving asylum patient. Optional rescue NPC. If saved, appears in endings and grants lore.
### Interaction
```
BP_NPC_Survivor
Implements: I_Interactable
Event Interact:
├─ [Dialogue Choice]
│ ├─ BPC_DialogueChoiceSystem.PresentChoices()
│ ├─ Options:
│ │ ├─ "Who are you? What happened here?" → Lore dump
│ │ ├─ "Follow me. I'll get you out." → NPC follows player
│ │ └─ "Stay here. It's safer." → NPC stays, gives item
│ │
│ ├─ Choice → BPC_BranchingConsequenceSystem.ExecuteConsequence()
│ │ ├─ Follow: NPC becomes follower, can carry items
│ │ └─ Stay: NPC gives Keycard Alpha (if not found yet)
│ │
│ └─ BPC_EndingAccumulator.RecordEvent("SurvivorSaved")
└─ Return True
```
### Survivor States
| State | Behavior |
|-------|----------|
| Idle | Sits in room, waits for player |
| Following | Walks behind player, stops when player stops |
| Hiding | If enemies near, finds hiding spot |
| Dead | If attacked by enemies during escort |
| Saved | Reaches safe room ending flag set |
---
## Enemy Spawning & Difficulty
### BPC_ProceduralEncounter (92) Configuration
| Encounter | DA_EncounterData | Difficulty Scalar |
|-----------|-----------------|:---:|
| WardA Patrol | `DA_Encounter_WardA_Patrol` | ×1.0 |
| WardB Mixed | `DA_Encounter_WardB_Mixed` | ×1.2 |
| Basement Shade | `DA_Encounter_ShadeAmbush` | ×1.5 |
### BPC_DifficultyManager (89) Scaling
```
Player deaths in current chapter:
0 deaths → Difficulty × 1.0 (normal)
1 death → Difficulty × 0.9 (slightly easier)
2 deaths → Difficulty × 0.8 (noticeably easier)
3+ deaths→ Difficulty × 0.7 (easier + extra checkpoints)
Difficulty affects:
├─ Enemy count: × Difficulty (rounded down)
├─ Enemy health: × Difficulty
├─ Enemy damage: × Difficulty
├─ Ammo spawn count: × (2.0 - Difficulty) [more ammo when easier]
├─ Stress accumulation rate: × Difficulty
└─ Scare event frequency: × Difficulty
```
---
## Enemy Death & Persistence
When an enemy is killed:
```
Enemy Health = 0
├─ [Death Animation] Montage plays (GASP death state)
├─ [Ragdoll] Enable physics on skeletal mesh
├─ [Corpse Persistence]
│ ├─ BPC_PersistentCorpseSystem.SaveCorpse()
│ └─ Corpse remains in world until:
│ ├─ Player leaves level (transition)
│ ├─ Save/Load cycle (corpse ID saved)
│ └─ Manual "clear corpses" via Void shift
├─ [Loot Drop] (30% chance)
│ └─ Spawn random item at corpse location:
│ ├─ Patient: Battery (40%), MedKit (30%), Ammo (20%), Nothing (10%)
│ └─ Orderly: Ammo (40%), Key item hint (30%), Battery (20%), Nothing (10%)
├─ [Metrics]
│ ├─ BPC_PlayerMetricsTracker.RecordKill(EnemyType, WeaponUsed)
│ └─ BPC_ProgressStatTracker.IncrementEnemiesKilled()
├─ [Stress Effect]
│ └─ Player BPC_StressSystem.AddStress(10) — "killing a former human"
└─ [Achievement Check]
└─ SS_AchievementSystem.Check("FirstKill", "Pacifist", "Exterminator")
```
---
## Blueprint Wiring Checklist
### Patient Enemy
- [ ] Create `BP_Enemy_Patient` child of `BP_EnemyBase`
- [ ] Add alert, AI state machine, perception, memory, behavior variant, damage reception, hit reaction components
- [ ] Create `AI_PatientController` child of `AI_BaseAgentController`
- [ ] Create `BT_PatientBehavior` Patrol/Search/Combat branches
- [ ] Create `BB_PatientData` all blackboard keys
- [ ] Create `DA_BehaviourVariant_Patient` with 3 variants + weights
- [ ] Set max health = 100, walk speed = 250, damage = 20
### Orderly Enemy
- [ ] Create `BP_Enemy_Orderly` child of `BP_EnemyBase`
- [ ] Same components as Patient
- [ ] Add flashlight vulnerability logic in AI controller (OnPerceptionUpdated check light)
- [ ] Create `AI_OrderlyController`, `BT_OrderlyBehavior`, `BB_OrderlyData`
- [ ] Set max health = 75, walk speed = 500, damage = 15
### Shade Enemy
- [ ] Create `BP_Enemy_Shade` child of `BP_EnemyBase`
- [ ] Add Teleport, VoidGlow, PhaseShift components
- [ ] Add `BPC_FearSystem` (fear aura)
- [ ] Create `AI_ShadeController` with dark-node pathfinding
- [ ] Create `BT_ShadeBehavior` VoidHunt/Stalk branches
- [ ] Create `BB_ShadeData` DarkNodes array, stunned state
- [ ] Set health = invulnerable, damage = 100 (one-hit)
### NPC Survivor
- [ ] Create `BP_NPC_Survivor` child of `Character`
- [ ] Implement `I_Interactable`
- [ ] Wire dialogue choices via `BPC_DialogueChoiceSystem`
- [ ] Wire follow/hide behaviors
---
## Notes for Expansion
- Add **boss encounters**: Void Entity manifestation (multi-phase boss fight)
- Add **stealth kill mechanic**: sneak behind Patient silent takedown (no stress penalty)
- Add **enemy variants**: "Blind Patient" (hearing-only), "Crawler" (ceiling enemy)
- Add **dynamic music**: combat music intensity scales with number of alert enemies
- Add **enemy faction system**: Patients flee from Shade, Orderlies protect Shade
- Multiplayer: server-authoritative AI, perception events replicated to all clients
- Consider **Procedural placement**: spawn points randomized each new game for replayability
---
*Enemies Index for Project Void. See [GAMEINDEX.md](GAMEINDEX.md) for full game structure. See [80_BP_EnemyBase.md](../blueprints/09-ai/80_BP_EnemyBase.md) for base enemy spec.*