Enhance documentation with Manual Implementation Guides and Build Checklists
- Updated `CONTEXT.md` to reference the new Manual Implementation Guide and Build Checklist in blueprint spec files. - Added a detailed Manual Implementation Guide to `01_GI_GameTagRegistry.md`, including class setup, variable initialization, function implementations, and a build checklist. - Introduced a Manual Implementation Guide section in `22_BPC_PhysicsDragSystem.md` with step-by-step instructions for setup and function logic. - Expanded `28_BPC_ConsumableSystem.md` with a comprehensive Manual Implementation Guide detailing class setup, variable initialization, function implementations, and networking. - Enhanced `69_BP_WeaponBase.md` with a Manual Implementation Guide covering class setup, variable defaults, function implementations, and networking. - Added a Manual Implementation Guide to `84_AI_BaseAgentController.md`, outlining class setup, variable initialization, function implementations, and networking. - Updated `TEMPLATE.md` to version 2.0, incorporating the Manual Implementation Guide and Build Checklist for human implementers. - Revised `INDEX.md` to reflect the new purpose and content of blueprint specifications, emphasizing the inclusion of the Manual Implementation Guide.
This commit is contained in:
@@ -146,4 +146,205 @@ Base class for all weapon actors (ranged and melee). Provides common weapon life
|
||||
| Owner (Player Character) | Direct | Animation blueprint queries weapon state |
|
||||
|
||||
### Reuse Notes
|
||||
Subclass for ranged or melee specific fire implementations. The state machine prevents firing during reload, equip, or holster sequences. Weapons are data-driven via `DA_WeaponData` — design changes never require blueprint edits.
|
||||
Subclass for ranged or melee specific fire implementations. The state machine prevents firing during reload, equip, or holster sequences. Weapons are data-driven via `DA_WeaponData` — design changes never require blueprint edits.
|
||||
|
||||
---
|
||||
|
||||
## Manual Implementation Guide
|
||||
|
||||
### Class Setup
|
||||
1. Create Blueprint Class: Parent = `Actor`, Name = `BP_WeaponBase`
|
||||
2. Save to: `Content/Framework/Weapons/`
|
||||
3. Add components in Construction Script:
|
||||
- `WeaponRoot` (SceneComponent) — root
|
||||
- `SkeletalMesh` (SkeletalMeshComponent) — attached to root
|
||||
4. Set `Replicates` = true in Class Defaults
|
||||
|
||||
### Variable Defaults (Class Defaults)
|
||||
| Variable | Type | Default |
|
||||
|----------|------|---------|
|
||||
| `WeaponState` | `EWeaponState` | `Holstered` |
|
||||
| `HolsterSocket` | `Name` | `weapon_holster` |
|
||||
| `EquipSocket` | `Name` | `weapon_equip` |
|
||||
| `AimDownSightsFOV` | `Float` | `55.0` |
|
||||
| `DefaultFOV` | `Float` | `90.0` |
|
||||
| `ADSInterpSpeed` | `Float` | `10.0` |
|
||||
| `bIsAiming` | `Boolean` | `false` |
|
||||
| `bCanFire` | `Boolean` | `true` |
|
||||
| `EquipDuration` | `Float` | `0.5` |
|
||||
| `HolsterDuration` | `Float` | `0.5` |
|
||||
| `RecoilPitch` | `Float` | `2.0` |
|
||||
| `RecoilYaw` | `Float` | `0.5` |
|
||||
|
||||
### Function Implementations
|
||||
|
||||
#### `Equip(CharacterOwner: Character)` → `void`
|
||||
|
||||
```
|
||||
[Function: Equip]
|
||||
Step 1: Branch on WeaponState == Holstered → If not, return (can't equip twice)
|
||||
Step 2: SetWeaponState(Equipping)
|
||||
Step 3: AttachToComponent(CharacterOwner.Mesh, EquipSocket)
|
||||
- Set Relative Location = (0,0,0)
|
||||
- Set Relative Rotation = (0,0,0)
|
||||
Step 4: Set Actor Hidden In Game = false
|
||||
Step 5: Play equip animation on SkeletalMesh (if montage exists)
|
||||
Step 6: Start timer for EquipDuration:
|
||||
└─ On timer complete:
|
||||
- SetWeaponState(Ready)
|
||||
- Set bCanFire = true
|
||||
- Fire OnWeaponEquipped(Self)
|
||||
```
|
||||
|
||||
**Nodes:** `Switch on EWeaponState`, `Attach Actor to Component`, `Set Actor Hidden In Game`, `Play Animation`, `Set Timer by Event`
|
||||
|
||||
#### `Holster()` → `void`
|
||||
|
||||
```
|
||||
[Function: Holster]
|
||||
Step 1: Branch on WeaponState == Ready OR Firing → If not, return
|
||||
Step 2: If WeaponState == Firing: StopFire first
|
||||
Step 3: SetWeaponState(Holstering)
|
||||
Step 4: Play holster animation on SkeletalMesh
|
||||
Step 5: Start timer for HolsterDuration:
|
||||
└─ On timer complete:
|
||||
- AttachToComponent(CharacterOwner.Mesh, HolsterSocket)
|
||||
- SetWeaponState(Holstered)
|
||||
- Fire OnWeaponHolstered(Self)
|
||||
```
|
||||
|
||||
#### `StartFire()` → `void`
|
||||
|
||||
```
|
||||
[Function: StartFire]
|
||||
Step 1: Branch on WeaponState == Ready (only fire from Ready state):
|
||||
False → Return
|
||||
Step 2: Call CanFire() → Branch on result:
|
||||
False → Return
|
||||
Step 3: SetWeaponState(Firing)
|
||||
Step 4: Fire OnFireStarted
|
||||
Step 5: Call OnFire() — this is the subclass override point (virtual function)
|
||||
Step 6: Switch on WeaponData.FireMode:
|
||||
Case SemiAutomatic:
|
||||
- Set bCanFire = false
|
||||
- Set timer by WeaponData.FireRate → on complete: Set bCanFire = true
|
||||
Case FullAutomatic:
|
||||
- Start looping timer (interval = WeaponData.FireRate)
|
||||
- Each tick: Call OnFire()
|
||||
Case BurstFire:
|
||||
- Loop 3 times with WeaponData.FireRate delay between each
|
||||
- On burst complete: SetWeaponState(Ready)
|
||||
```
|
||||
|
||||
**Important:** `OnFire()` is a **BlueprintImplementableEvent** — it has NO body in BP_WeaponBase. Subclasses (BP_RangedWeapon, BP_MeleeWeapon) override it with their own fire logic.
|
||||
|
||||
#### `StopFire()` → `void`
|
||||
|
||||
```
|
||||
[Function: StopFire]
|
||||
Step 1: Branch on WeaponState == Firing:
|
||||
False → Return
|
||||
Step 2: If FireMode == FullAutomatic OR BurstFire:
|
||||
- Clear all FireRate timers
|
||||
Step 3: SetWeaponState(Ready)
|
||||
Step 4: Fire OnFireStopped
|
||||
```
|
||||
|
||||
#### `CanFire()` → `Boolean`
|
||||
|
||||
```
|
||||
[Function: CanFire] (Pure)
|
||||
Step 1: Branch on WeaponState == Ready → If not, return false
|
||||
Step 2: Branch on bCanFire → If not, return false (on cooldown)
|
||||
Step 3: Get AmmoComponent from Owner → Call HasAmmo()
|
||||
- If no ammo: return false (subclass may trigger auto-reload)
|
||||
Step 4: Get Owner → Get BPC_StateManager → Call IsActionPermitted(GameplayTag: "Action.Fire")
|
||||
- If not permitted: return false
|
||||
Step 5: Return true
|
||||
```
|
||||
|
||||
#### `StartReload()` → `void`
|
||||
|
||||
```
|
||||
[Function: StartReload]
|
||||
Step 1: Branch on WeaponState == Ready:
|
||||
False → Return (can't reload while firing/holstered)
|
||||
Step 2: Branch on AmmoComponent.IsMagazineFull():
|
||||
True → Return (no need to reload)
|
||||
Step 3: Branch on AmmoComponent.HasReserveAmmo():
|
||||
False → Return (no ammo to load)
|
||||
Step 4: SetWeaponState(Reloading)
|
||||
Step 5: Fire OnReloadStarted
|
||||
Step 6: Play reload animation montage:
|
||||
- Use AnimNotify "OnReloadComplete" at the ammo-insert frame
|
||||
- AnimNotify handler: call FinishReload()
|
||||
```
|
||||
|
||||
#### `FinishReload()` → `void`
|
||||
|
||||
```
|
||||
[Function: FinishReload]
|
||||
Step 1: Get AmmoComponent → Call RefillAmmo(MagazineSize from WeaponData)
|
||||
Step 2: SetWeaponState(Ready)
|
||||
Step 3: Fire OnReloadCompleted
|
||||
```
|
||||
|
||||
#### `StartAim()` → `void`
|
||||
|
||||
```
|
||||
[Function: StartAim]
|
||||
Step 1: Set bIsAiming = true
|
||||
Step 2: Get Owner → Get PlayerController → Get PlayerCameraManager
|
||||
Step 3: Set PlayerCameraManager Field of View to AimDownSightsFOV with interp speed
|
||||
Step 4: Fire OnAimStarted
|
||||
```
|
||||
|
||||
#### `StopAim()` → `void`
|
||||
|
||||
```
|
||||
[Function: StopAim]
|
||||
Step 1: Set bIsAiming = false
|
||||
Step 2: Get PlayerCameraManager → Set FOV to DefaultFOV with interp
|
||||
Step 3: Fire OnAimStopped
|
||||
```
|
||||
|
||||
#### `SetWeaponState(NewState: EWeaponState)` → `void`
|
||||
|
||||
```
|
||||
[Function: SetWeaponState]
|
||||
Step 1: OldState = WeaponState
|
||||
Step 2: If NewState == OldState → Return
|
||||
Step 3: WeaponState = NewState
|
||||
Step 4: Mark variable dirty (for replication)
|
||||
Step 5: Fire OnWeaponStateChanged(NewState, OldState)
|
||||
```
|
||||
|
||||
### Event Dispatcher Bindings
|
||||
|
||||
| Bind to Dispatcher | Custom Event | Logic |
|
||||
|-------------------|-------------|-------|
|
||||
| `IA_Fire` (Pressed) | `OnFirePressed` | Call StartFire() |
|
||||
| `IA_Fire` (Released) | `OnFireReleased` | Call StopFire() |
|
||||
| `IA_Reload` (Pressed) | `OnReloadPressed` | Call StartReload() |
|
||||
| `IA_Aim` (Pressed) | `OnAimPressed` | Call StartAim() |
|
||||
| `IA_Aim` (Released) | `OnAimReleased` | Call StopAim() |
|
||||
|
||||
### Networking
|
||||
- **WeaponState** replicated with `OnRep_WeaponState` → plays matching animation on remote clients
|
||||
- **All state transitions** are server-authoritative via `Server_StartFire`, `Server_StartReload`, etc.
|
||||
- Client predicts: fire animation, muzzle flash, recoil (cosmetic only)
|
||||
- Server validates: ammo count, fire rate cooldown, state machine transitions
|
||||
|
||||
### Blueprint Build Checklist
|
||||
- [ ] Create BP_WeaponBase actor with WeaponRoot + SkeletalMesh components
|
||||
- [ ] Add EquipmentSocket component on Player Character (weapon_equip, weapon_holster)
|
||||
- [ ] Add all variables with correct types and defaults
|
||||
- [ ] Implement Equip/Holster with attach/detach and animation timers
|
||||
- [ ] Implement StartFire/StopFire with fire rate timer loop
|
||||
- [ ] Create OnFire as BlueprintImplementableEvent (empty — subclasses override)
|
||||
- [ ] Implement CanFire checks: state, cooldown, ammo, StateManager permission
|
||||
- [ ] Implement StartReload/FinishReload with animation notify
|
||||
- [ ] Implement StartAim/StopAim with FOV interpolation
|
||||
- [ ] Implement SetWeaponState with old state tracking and dispatcher
|
||||
- [ ] Bind all input actions (Fire, Reload, Aim)
|
||||
- [ ] Add networking: replicated WeaponState, Server_ RPCs for all mutators
|
||||
Reference in New Issue
Block a user