Files
UE5-Modular-Game-Framework/docs/game/weapons-index.md
Lefteris Notas 040db37720 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.
2026-05-21 22:27:57 +03:00

317 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Weapons Index — All Held Weapon Actors
**Game:** Project Void | **Build Phase:** 10
**Framework Systems:** 69_BP_WeaponBase, 70_BPC_AmmoComponent, 74_BPC_FirearmSystem, 76_BPC_MeleeSystem, 77_BPC_RecoilSystem, 78_BPC_ReloadSystem
---
## Purpose
Defines the 4 held weapon/tool actors used by the player. Each is spawned by `BPC_EquipmentSlotSystem` when an item is equipped and attached to the player's hand socket.
---
## Weapon Catalog
| # | Actor | Type | Damage | Fire Rate | Mag Size | Slot | Interfaces |
|---|-------|------|:---:|:---:|:---:|------|------------|
| 1 | `BP_Pistol_Held` | Firearm | 15 | 0.15s (hitscan) | 12 | PrimaryWeapon | I_UsableItem |
| 2 | `BP_Shotgun_Held` | Firearm | 45 (total) | 1.0s (pellets) | 2 | PrimaryWeapon | I_UsableItem |
| 3 | `BP_Flashlight_Held` | Tool | 0 | — | — | Tool | I_UsableItem, I_Toggleable |
| 4 | `BP_Crowbar_Held` | Melee/Tool | 20 | 0.8s (swing) | — | Tool | I_UsableItem, I_MeleeWeapon |
---
## 1. BP_Pistol_Held (Full build in [item-pistol.md](item-pistol.md))
**Quick Reference:**
```
Components:
├─ SkeletalMeshComponent (slide animation)
├─ SceneComponent "MuzzleSocket"
├─ AudioComponent "FireSound"
├─ AudioComponent "ReloadSound"
└─ ParticleSystemComponent "MuzzleFlash"
Core Loop:
IA_Fire → UseItem() → Ammo check → Hitscan → Damage → Recoil → Timer lockout
IA_Reload → Reload() → BPC_AmmoComponent.ConsumeAmmo() → update magazine
States:
├─ Idle (can fire)
├─ Firing (timer lockout)
├─ Empty (out of ammo — click sound)
└─ Reloading (animation, blocked input)
```
---
## 2. BP_Shotgun_Held
**Parent:** `BP_WeaponBase` (69)
### Components
| # | Component | Name | Purpose |
|---|-----------|------|---------|
| 1 | `SkeletalMeshComponent` | `WeaponMesh` | Break-action double barrel |
| 2 | `SceneComponent` | `MuzzleSocket` | End of barrel |
| 3 | `AudioComponent` | `FireSound` | Loud shotgun blast |
| 4 | `AudioComponent` | `ReloadSound` | Shell insertion click |
| 5 | `AudioComponent` | `BreakOpenSound` | Opening action sound |
| 6 | `AudioComponent` | `BreakCloseSound` | Closing action snap |
| 7 | `ParticleSystemComponent` | `MuzzleFlash` | Large muzzle flash |
| 8 | `PointLightComponent` | `MuzzleLight` | Brief flash on fire |
### Variables
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `CurrentShells` | Int | `2` | Shells currently loaded (0-2) |
| `MaxShells` | Int | `2` | Always 2 for double-barrel |
| `bIsFiring` | Bool | `false` | Fire lockout |
| `bIsReloading` | Bool | `false` | Reload lockout |
| `bIsBrokenOpen` | Bool | `false` | Break-action state |
| `WeaponData` | DA_ItemData* | — | Shotgun Data Asset |
| `PelletCount` | Int | `6` | Pellets per shot |
| `PelletSpreadAngle` | Float | `5.0` | Degrees of spread cone |
### Fire Logic (Pellet Spread)
```
UseItem() → (called by IA_Fire or IA_Fire+IA_Aim for ADS)
├─ bIsFiring? → Return False
├─ bIsReloading? → Return False
├─ bIsBrokenOpen? → Auto-close barrels → wait 0.3s
├─ CurrentShells > 0? → Branch
│ ├─ True:
│ │ ├─ Set bIsFiring = true
│ │ ├─ CurrentShells -= 1
│ │ │
│ │ ├─ [Fire Both Barrels if 2 shells loaded?]
│ │ │ └─ Designer option: single or double fire
│ │ │ └─ Default: single fire (double on alt-fire)
│ │ │
│ │ ├─ [Multi-Trace Pellet System]
│ │ │ │
│ │ │ ├─ For i = 0 to PelletCount:
│ │ │ │ ├─ Calculate spread direction:
│ │ │ │ │ ├─ BaseDir: Camera forward vector
│ │ │ │ │ └─ Apply Random Cone (PelletSpreadAngle)
│ │ │ │ │
│ │ │ │ ├─ Start: MuzzleSocket.GetWorldLocation
│ │ │ │ ├─ End: Start + SpreadDir * FireRange
│ │ │ │ │
│ │ │ │ └─ Line Trace By Channel (Visibility)
│ │ │ │ ├─ Hit? → Branch
│ │ │ │ │ ├─ True:
│ │ │ │ │ │ ├─ HitActor → I_Damageable?
│ │ │ │ │ │ │ └─ ApplyDamage(PelletDamage, ...)
│ │ │ │ │ │ └─ Spawn impact decal
│ │ │ │ │ └─ False: continue
│ │ │ │ └─ Draw debug line (editor only, color per pellet)
│ │ │ │
│ │ │ └─ Track total pellets hit for combat feedback
│ │ │
│ │ ├─ [Effects]
│ │ │ ├─ MuzzleFlash → Activate
│ │ │ ├─ FireSound → Play
│ │ │ ├─ MuzzleLight → SetVisibility(true) → Delay(0.05) → false
│ │ │ └─ Camera shake (heavy): PlayCameraShake(ShotgunKick)
│ │ │
│ │ ├─ [Recoil]
│ │ │ └─ BPC_RecoilSystem.ApplyRecoil(WeaponData, ×3 heavy multiplier)
│ │ │
│ │ ├─ [Post-Fire]
│ │ │ ├─ Delay(FireRateTimer) → Set bIsFiring = false
│ │ │ └─ IF CurrentShells == 0 → Auto-break-open for reload
│ │ │ └─ Set bIsBrokenOpen = true, play break animation
│ │ │
│ │ └─ Return True
│ │
│ └─ False: (empty)
│ ├─ Play click/empty sound
│ └─ Return False
```
### Reload Logic (Shell-by-Shell)
```
Reload()
├─ CurrentShells >= MaxShells? → Return (full)
├─ bIsReloading? → Return (already reloading)
├─ [If not broken open] → Play break-open animation → Set bIsBrokenOpen = true
├─ Set bIsReloading = true
├─ [Shell Loop — reload one shell at a time]
│ │
│ ├─ BPC_AmmoComponent.GetAmmoCount(ShellAmmoTypeTag)
│ │
│ ├─ While CurrentShells < MaxShells AND BPC_AmmoComponent.AmmoCount > 0:
│ │ ├─ BPC_AmmoComponent.ConsumeAmmo(ShellAmmoTypeTag, 1)
│ │ ├─ CurrentShells += 1
│ │ ├─ Play ReloadSound (shell click)
│ │ └─ Delay(ShellReloadDelay = 0.8s)
│ │
│ └─ [Player CAN fire mid-reload if at least 1 shell loaded]
│ └─ If IA_Fire pressed during reload:
│ ├─ Stop reload loop
│ ├─ Play break-close animation
│ ├─ Set bIsBrokenOpen = false
│ ├─ Set bIsReloading = false
│ └─ Process Fire (with whatever shells are loaded)
├─ [Reload Complete]
│ ├─ Play break-close animation
│ ├─ Set bIsBrokenOpen = false
│ ├─ Set bIsReloading = false
│ └─ Broadcast OnReloadComplete
```
### Damage Falloff
```
CalculatePelletDamage(BaseDamage, Distance):
├─ IF Distance <= 500: multiplier = 1.0 (point-blank: devastating)
├─ IF Distance <= 1500: multiplier = 0.7 (close range: lethal)
├─ IF Distance <= 2500: multiplier = 0.4 (medium: wounding)
└─ IF Distance > 2500: multiplier = 0.15 (long: minor)
└─ Return BaseDamage × multiplier / PelletCount
```
---
## 3. BP_Flashlight_Held (Full build in [item-flashlight.md](item-flashlight.md))
**Quick Reference:**
- Implements `I_UsableItem` and `I_Toggleable`
- UseItem() → toggles light on/off
- Battery consumed at 2%/second while on
- Battery restored by using `DA_Item_Battery` from consumable system
- SpotLightComponent with Cone Angle: 15° / 30°
---
## 4. BP_Crowbar_Held
**Parent:** `Actor` | **Implements:** `I_UsableItem`, `I_MeleeWeapon`
### Components
| # | Component | Name | Purpose |
|---|-----------|------|---------|
| 1 | `StaticMeshComponent` | `CrowbarMesh` | Rusted crowbar model |
| 2 | `BoxComponent` | `SwingHitbox` | Melee hit detection (disabled until swing) |
### Variables
| Variable | Type | Default | Purpose |
|----------|------|---------|---------|
| `SwingDamage` | Float | `20.0` | Damage per swing |
| `SwingCooldown` | Float | `0.8` | Seconds between swings |
| `bIsSwinging` | Bool | `false` | Swing lockout |
| `SwingRange` | Float | `250.0` | Units of reach |
| `SwingArc` | Float | `90.0` | Degrees of arc |
### Melee Logic
```
UseItem() → BPC_MeleeSystem.Swing(Self)
├─ bIsSwinging? → Return False
├─ Set bIsSwinging = true
├─ [Swing Animation]
│ └─ Timeline (0.0 → 1.0 over 0.3s) → Update crowbar rotation
├─ [Swing Hitbox — enable at 0.15s (mid-swing)]
│ ├─ Delay(0.15) → SwingHitbox.SetCollisionEnabled(QueryOnly)
│ ├─ OnComponentBeginOverlap(SwingHitbox, OtherActor):
│ │ ├─ OtherActor → DoesImplementInterface(I_Damageable)?
│ │ │ ├─ True:
│ │ │ │ ├─ ApplyDamage(SwingDamage, Self, Melee, HitLocation, HitDirection)
│ │ │ │ ├─ Play hit sound (metal thud)
│ │ │ │ └─ BPC_CombatFeedbackComponent.ShowHitMarker()
│ │ │ └─ False: Play wall/object hit sound
│ │ └─ (Hit each actor only once per swing — use a hit-set)
│ │
│ └─ Delay(0.15) → SwingHitbox.SetCollisionEnabled(NoCollision)
├─ [Swing Complete]
│ ├─ Delay(SwingCooldown) → Set bIsSwinging = false
│ └─ Return True
```
### Pry Function
```
CanPryOpen(DoorActor: BP_DoorActor*) → Boolean
└─ Return (DoorActor.IsBarricaded())
PryDoor(DoorActor: BP_DoorActor*)
├─ DoorActor.Open() (forces open, breaks barricade)
├─ Play wood/metal break sound
├─ DoorActor.SetLocked(false) permanently
└─ SS_AudioManager.PlaySFX("crowbar_pry")
```
---
## Weapon Animation Notifies (GASP Integration)
All held weapons fire animation notifies that the GASP AnimBP listens to:
| Notify | Weapon | Purpose |
|--------|--------|---------|
| `Notify_Fire` | Pistol, Shotgun | Triggers fire animation blend |
| `Notify_ReloadStart` | Pistol, Shotgun | Enters reload animation state |
| `Notify_ReloadEnd` | Pistol, Shotgun | Exits reload animation state |
| `Notify_MeleeSwing` | Crowbar | Triggers melee swing blend |
| `Notify_Equip` | All | Weapon equip animation |
| `Notify_Unequip` | All | Weapon holster animation |
| `Notify_AimDownSights` | Pistol, Shotgun | ADS pose transition |
| `Notify_HipFire` | Pistol, Shotgun | Hip fire pose transition |
These are added to montage slots in the **GASP child AnimBP**, NOT in the weapon BP itself.
---
## Quick Comparison
| Feature | Pistol | Shotgun | Flashlight | Crowbar |
|---------|--------|---------|-----------|---------|
| **Role** | Ranged DPS | Burst damage | Vision | Utility + Melee |
| **Best Range** | Medium-Long | Close | Infinite (light) | Melee |
| **Ammo Management** | Magazine | Shell-by-shell | Battery (%) | None |
| **Reload Strategy** | Dump + reload | Tactical (can interrupt) | Replace battery | N/A |
| **Recoil** | Light | Heavy | None | None |
| **ADS Benefit** | Higher accuracy | Tighter spread | N/A | N/A |
| **Stress Impact** | None | +5 (loud) | -1/sec (safe light) | None |
| **Silent?** | No | No | Yes | No (swing noise) |
| **Attracts Enemies?** | Yes (2000u radius) | Yes (3000u radius) | Yes (800u radius) | Yes (1200u radius) |
---
## Notes for Expansion
- Add **weapon degradation**: pistol jams after 100 shots without cleaning
- Add **flashlight flicker**: battery below 10% causes random light flicker (horror mechanic)
- Add **shotgun slug ammo**: alternate ammo type — single slug instead of pellets, longer range
- Add **crowbar upgrade**: wrap with cloth → silent melee swings (no enemy alert)
- Add **aim-assist** for controller players (configurable in accessibility)
- Add **weapon inspection animation**: hold reload key to inspect weapon (cosmetic)
- Multiplayer: all fire/reload must be server-authoritative with client prediction for effects
---
*Weapons Index for Project Void. See [GAMEINDEX.md](GAMEINDEX.md) for full game structure. See [item-pistol.md](item-pistol.md) and [item-flashlight.md](item-flashlight.md) for detailed build walkthroughs.*