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:
@@ -181,7 +181,7 @@ docs/
|
||||
- **Input Mode Coordination:** `SS_EnhancedInputManager` syncs cursor visibility and input blocking with `SS_UIManager` on menu open/close.
|
||||
|
||||
## Conventions for Blueprint Spec Files
|
||||
Each file in `docs/blueprints/` follows the template defined in `docs/blueprints/TEMPLATE.md`. Files define: Enums, Structs, Variables, Functions, Event Dispatchers, Flow Diagram, Communication Matrix, and Reuse Notes.
|
||||
Each file in `docs/blueprints/` follows the template defined in [`docs/blueprints/TEMPLATE.md`](docs/blueprints/TEMPLATE.md) (v2.0). Files define: Enums, Structs, Variables, Functions, Event Dispatchers, Flow Diagram, Communication Matrix, Reuse Notes, **Manual Implementation Guide** (node-by-node logic for human implementers), and Build Checklist.
|
||||
|
||||
## Documentation Update Protocol (CRITICAL RULE)
|
||||
**Any change to the framework MUST also update these files in the same commit:**
|
||||
|
||||
@@ -177,16 +177,106 @@ This asset does not talk to other systems directly. All communication is passive
|
||||
|
||||
---
|
||||
|
||||
## 14. Blueprint Implementation Steps (for Blueprint Agent)
|
||||
## 14. Manual Implementation Guide
|
||||
|
||||
1. Create a new **Data Asset** class.
|
||||
2. Parent: `UPrimaryDataAsset`
|
||||
> **For human implementer:** Follow these steps to build `DA_GameTagRegistry` in UE5.
|
||||
|
||||
### 14.1 Class Setup
|
||||
|
||||
1. Right-click in Content Browser → **Miscellaneous → Data Asset**
|
||||
2. Select parent class: `PrimaryDataAsset`
|
||||
3. Name: `DA_GameTagRegistry`
|
||||
4. Save to: `/Game/Framework/Core/DA_GameTagRegistry`
|
||||
5. Add variables `TagNamespace` (FText) and `bIsFrameworkTag` (bool).
|
||||
6. Implement the functions listed in Section 6 as Blueprint Callable / Pure nodes.
|
||||
7. Document all tag namespaces from Section 10 in the asset's description.
|
||||
8. Save and run the validation test.
|
||||
4. Save to: `Content/Framework/Core/`
|
||||
|
||||
### 14.2 Variables
|
||||
|
||||
Add to Class Defaults:
|
||||
| Variable | Type | Instance Editable | Default |
|
||||
|----------|------|------------------|---------|
|
||||
| `TagNamespace` | `Text` | ✓ | *Framework tag namespace description* |
|
||||
| `bIsFrameworkTag` | `Boolean` | ✓ | `true` |
|
||||
|
||||
There are NO tag entries stored in this asset. Tags live in `Project Settings → GameplayTags` or `DefaultGameplayTags.ini`.
|
||||
|
||||
### 14.3 Function Implementations
|
||||
|
||||
#### `GetAllRegisteredTags` → `Array of GameplayTag`
|
||||
|
||||
**Purpose:** Returns every tag registered in the project.
|
||||
|
||||
**Nodes to Use (Blueprint Implementable Function):**
|
||||
```
|
||||
[Function: GetAllRegisteredTags]
|
||||
└─ Get All Gameplay Tags (from GameplayTags subsystem)
|
||||
└─ Return the array
|
||||
```
|
||||
|
||||
**Node Search:** Right-click → "Get All Gameplay Tags"
|
||||
|
||||
#### `GetTagDisplayName(Tag)` → `Text`
|
||||
|
||||
**Nodes to Use (Blueprint Pure):**
|
||||
```
|
||||
[Function: GetTagDisplayName]
|
||||
Input Tag → Get Tag Display Name (from GameplayTags)
|
||||
└─ Return the text
|
||||
```
|
||||
|
||||
**Node Search:** Right-click → "Get Tag Display Name"
|
||||
|
||||
#### `ValidateTag(Tag)` → `Boolean`
|
||||
|
||||
**Nodes to Use (Blueprint Pure / Callable):**
|
||||
```
|
||||
[Function: ValidateTag]
|
||||
Input Tag → Is Valid Tag (from GameplayTags)
|
||||
Branch on result:
|
||||
True → Return true
|
||||
False → Print Warning: "Invalid Tag: {Tag}" → Return false
|
||||
```
|
||||
|
||||
**Node Search:** Right-click → "Is Gameplay Tag Valid"
|
||||
|
||||
#### `LogAllTags` → *(void)*
|
||||
|
||||
**Blueprint Callable — Editor Only:**
|
||||
```
|
||||
[Function: LogAllTags]
|
||||
├─ Get All Gameplay Tags → ForEachLoop
|
||||
│ └─ Print String: Tag.ToString()
|
||||
└─ Print String: "Total tags: {Array Length}"
|
||||
```
|
||||
|
||||
**Node Search:** Right-click → "ForEachLoop", "Print String"
|
||||
|
||||
#### `ExportTagNamespace(NamespacePrefix)` → `String`
|
||||
|
||||
**Blueprint Callable:**
|
||||
```
|
||||
[Function: ExportTagNamespace]
|
||||
├─ Get All Gameplay Tags
|
||||
├─ ForEachLoop:
|
||||
│ └─ Get Tag Name → ToString
|
||||
│ └─ Does string start with NamespacePrefix?
|
||||
│ True → Append to output string with newline
|
||||
└─ Return output string
|
||||
```
|
||||
|
||||
### 14.4 Networking
|
||||
|
||||
No replication needed. This is a read-only Data Asset. All clients load identical copies from disk.
|
||||
|
||||
### 14.5 Blueprint Build Checklist
|
||||
|
||||
- [ ] Create Data Asset: `DA_GameTagRegistry` (Parent: `PrimaryDataAsset`)
|
||||
- [ ] Add `TagNamespace` (Text) and `bIsFrameworkTag` (Bool) variables
|
||||
- [ ] Implement `GetAllRegisteredTags` function (Pure)
|
||||
- [ ] Implement `GetTagDisplayName` function (Pure)
|
||||
- [ ] Implement `ValidateTag` function (Pure)
|
||||
- [ ] Implement `LogAllTags` (Editor-only)
|
||||
- [ ] Implement `ExportTagNamespace` (Tooling)
|
||||
- [ ] Document all tag namespaces in the asset's Description field (use Section 10 as reference)
|
||||
- [ ] Verify: all tag namespaces from Section 10 exist in `DefaultGameplayTags.ini`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -102,3 +102,131 @@ ReleaseObject:
|
||||
## 8. Reuse Notes
|
||||
- Physics drag uses UE5 physics constraint system for realistic object handling
|
||||
- Objects must have `Simulate Physics = true` and `Mass` configured
|
||||
|
||||
---
|
||||
|
||||
## 9. Manual Implementation Guide
|
||||
|
||||
### 9.1 Class Setup
|
||||
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_PhysicsDragSystem`
|
||||
2. Save to: `Content/Framework/Interaction/`
|
||||
3. Add to your Player Character.
|
||||
|
||||
### 9.2 Variable Initialization (BeginPlay)
|
||||
|
||||
```
|
||||
Event BeginPlay
|
||||
├─ Set bIsGrabbing = false
|
||||
├─ Set GrabbedObject = None
|
||||
├─ Get Owner → Get Component by Class (BPC_InteractionDetector) → Store reference
|
||||
└─ Get Owner → Get PlayerCameraManager → Store for throw direction
|
||||
```
|
||||
|
||||
### 9.3 Function Implementations
|
||||
|
||||
#### `GrabObject(TargetActor: Actor)` → `Boolean`
|
||||
|
||||
**Node-by-Node Logic:**
|
||||
```
|
||||
[Function: GrabObject]
|
||||
Step 1: Branch on bIsGrabbing → If true, ReleaseObject first
|
||||
Step 2: Branch on IsValid(TargetActor) → If not, return false
|
||||
Step 3: Get TargetActor → Get Component by Class (StaticMeshComponent)
|
||||
└─ Check: Is Simulate Physics Enabled? → If not, Fire OnGrabFailed("No physics"), return false
|
||||
Step 4: Check mass: StaticMeshComponent.GetMass() → If > MaxGrabMass, fail
|
||||
Step 5: Switch on DragMode:
|
||||
Case PhysicsConstraint:
|
||||
- Create Physics Constraint component (spawn dynamically)
|
||||
- ConstraintComp.SetConstrainedComponents(StaticMeshComponent, None, PlayerHandBone)
|
||||
- Set Linear limits: X=Locked, Y=Locked, Z=Locked (or Free for dangling)
|
||||
- Set Angular limits: Free (can rotate), or limited
|
||||
Case Kinematic:
|
||||
- StaticMeshComponent.SetSimulatePhysics(false)
|
||||
- StaticMeshComponent.AttachToComponent(PlayerHandSocket)
|
||||
Case Magnetic:
|
||||
- Store target; handle in Tick with Lerp toward hand position
|
||||
Step 6: Set GrabbedObject = TargetActor
|
||||
Step 7: Set bIsGrabbing = true
|
||||
Step 8: Fire OnObjectGrabbed(TargetActor)
|
||||
Step 9: Return true
|
||||
```
|
||||
|
||||
**Nodes Used:** `IsValid`, `Get Component by Class (StaticMeshComponent)`, `Is Simulate Physics Enabled`, `Get Mass`, `Create Constraint`, `SetConstrainedComponents`, `AttachToComponent`, `Branch`
|
||||
|
||||
#### `ReleaseObject(bThrow: Boolean)` → `void`
|
||||
|
||||
```
|
||||
[Function: ReleaseObject]
|
||||
Step 1: Branch on bIsGrabbing → If false, return
|
||||
Step 2: Branch on bThrow AND bCanThrow:
|
||||
True:
|
||||
- Get PlayerCameraManager → Get Forward Vector
|
||||
- Multiply forward vector by ThrowForce
|
||||
- GrabbedObject.StaticMeshComponent.AddImpulse(throw vector)
|
||||
- OR: if ConstraintComp exists → BreakConstraint, then AddImpulse
|
||||
False:
|
||||
- Just release without force
|
||||
Step 3: Switch on DragMode:
|
||||
- PhysicsConstraint: Destroy ConstraintComp
|
||||
- Kinematic: DetachFromComponent, SetSimulatePhysics(true)
|
||||
- Magnetic: Clear target reference
|
||||
Step 4: Set GrabbedObject = None
|
||||
Step 5: Set bIsGrabbing = false
|
||||
Step 6: Fire OnObjectReleased(GrabbedObject, bThrow)
|
||||
```
|
||||
|
||||
**Nodes Used:** `Get Forward Vector`, `Multiply (Vector * Float)`, `Add Impulse`, `Break Constraint`, `Destroy Component`, `Detach From Component`, `Set Simulate Physics`
|
||||
|
||||
#### `RotateObject(YawInput: Float, PitchInput: Float, RollInput: Float)` → `void`
|
||||
|
||||
```
|
||||
[Function: RotateObject]
|
||||
Step 1: Branch on bIsGrabbing → If false, return
|
||||
Step 2: Create Rotator from inputs (use RotationSpeed multiplier)
|
||||
- NewRotation = Make Rotator(PitchInput * RotationSpeed * DeltaTime, YawInput * RotationSpeed * DeltaTime, RollInput * RotationSpeed * DeltaTime)
|
||||
Step 3: Switch on DragMode:
|
||||
- PhysicsConstraint: GrabbedObject.AddLocalRotation(NewRotation)
|
||||
- Kinematic: GrabbedObject.AddRelativeRotation(NewRotation)
|
||||
- Magnetic: Rotate the lerp target
|
||||
```
|
||||
|
||||
#### `SetHoldDistance(NewDistance: Float)` → `void`
|
||||
|
||||
```
|
||||
[Function: SetHoldDistance]
|
||||
Step 1: Clamp NewDistance between MinHoldDistance and MaxHoldDistance
|
||||
Step 2: Set HoldDistance = NewDistance
|
||||
Step 3: If DragMode == PhysicsConstraint:
|
||||
- ConstraintComp.SetLinearPositionTarget(PlayerCamera.ForwardVector * HoldDistance)
|
||||
Step 4: If DragMode == Kinematic:
|
||||
- Set Relative Location (X = HoldDistance, Y = 0, Z = 0) on attached component
|
||||
```
|
||||
|
||||
### 9.4 Event Dispatcher Bindings
|
||||
|
||||
| Bind to Dispatcher | Custom Event | Logic |
|
||||
|-------------------|-------------|-------|
|
||||
| Input Action: `IA_Grab` (Pressed) | `OnGrabPressed` | Get InteractionDetector.CurrentTarget → Call GrabObject |
|
||||
| Input Action: `IA_Grab` (Released) | `OnGrabReleased` | Call ReleaseObject(true) |
|
||||
| `BPC_InteractionDetector.OnTargetFound` | `OnGrabTargetFound(Target)` | Highlight grabbable object outline |
|
||||
|
||||
### 9.5 Networking
|
||||
|
||||
| Variable | Replication |
|
||||
|----------|-------------|
|
||||
| `bIsGrabbing` | `Replicated` |
|
||||
| `GrabbedObject` | `Replicated` (Actor reference) |
|
||||
|
||||
**Server RPC:** `Server_GrabObject(TargetActor)` — server validates range, spawns constraint. Physics is server-authoritative; client predicts locally.
|
||||
|
||||
### 9.6 Blueprint Build Checklist
|
||||
|
||||
- [ ] Create BPC_PhysicsDragSystem component, add to Player Character
|
||||
- [ ] Add all variables: DragMode, GrabbedObject, ConstraintComp, GrabDistance, HoldDistance, ThrowForce, RotationSpeed, bCanThrow, bIsGrabbing
|
||||
- [ ] Implement GrabObject with three drag modes (PhysicsConstraint, Kinematic, Magnetic)
|
||||
- [ ] Implement ReleaseObject with throw mechanic
|
||||
- [ ] Implement RotateObject with input axis mapping
|
||||
- [ ] Implement SetHoldDistance with scroll wheel input
|
||||
- [ ] Bind to IA_Grab input action (pressed/released)
|
||||
- [ ] Add MaxGrabMass config to prevent lifting impossibly heavy objects
|
||||
- [ ] Test: grab crate, rotate, throw — physics should feel natural
|
||||
@@ -60,3 +60,136 @@
|
||||
## 7. Reuse Notes
|
||||
- All consumable effects are data-driven via DA_ItemData
|
||||
- Buffs support stacking (multiple buffs active simultaneously)
|
||||
|
||||
---
|
||||
|
||||
## 8. Manual Implementation Guide
|
||||
|
||||
### 8.1 Class Setup
|
||||
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_ConsumableSystem`
|
||||
2. Save to: `Content/Framework/Inventory/`
|
||||
3. Add to your Player Character or Player Controller
|
||||
|
||||
### 8.2 Variable Initialization (BeginPlay)
|
||||
|
||||
```
|
||||
Event BeginPlay
|
||||
├─ Set ConsumableCooldown = 1.5 (or expose as config)
|
||||
├─ Set bCanUseConsumables = true
|
||||
├─ Set ActiveBuffs = empty array
|
||||
├─ Get Owner → Find Component by Class (BPC_InventorySystem) → Store reference
|
||||
│ └─ If found: Bind to BPC_InventorySystem.OnItemUsed → OnInventoryItemUsedHandler
|
||||
└─ Start a looping timer (0.1s) for TickBuffs
|
||||
```
|
||||
|
||||
### 8.3 Function Implementations
|
||||
|
||||
#### `UseConsumable(SlotIndex: Integer)` → `Boolean`
|
||||
|
||||
**Node-by-Node Logic:**
|
||||
```
|
||||
[Function: UseConsumable]
|
||||
Step 1: Branch on bCanUseConsumables → If false, return false
|
||||
Step 2: Get InventorySystem reference → Call GetItemAtSlot(SlotIndex) → returns S_InventoryEntry
|
||||
Step 3: Branch on IsValid(ItemData) → If not valid, return false
|
||||
Step 4: Check ItemData.ItemType == Consumable → If not, return false
|
||||
Step 5: Read ItemData.ConsumableData → get effect values:
|
||||
- HealthRestore, StaminaRestore, StressReduce, SpeedBuff, DamageBuff, BuffDuration
|
||||
Step 6: Apply effects (branch on each value > 0):
|
||||
- If HealthRestore > 0: Get BPC_HealthSystem → Call ApplyHealing(HealthRestore)
|
||||
- If StaminaRestore > 0: Get BPC_StaminaSystem → Call RestoreStamina(StaminaRestore)
|
||||
- If StressReduce > 0: Get BPC_StressSystem → Call RemoveStress(StressReduce)
|
||||
- If SpeedBuff > 0 AND BuffDuration > 0: Call ApplyBuff(SpeedBuffTag, BuffDuration)
|
||||
- If DamageBuff > 0 AND BuffDuration > 0: Call ApplyBuff(DamageBuffTag, BuffDuration)
|
||||
Step 7: If any buff applied: add to ActiveBuffs array with RemainingDuration = BuffDuration
|
||||
Step 8: Fire OnConsumableUsed (pass the InventoryEntry)
|
||||
Step 9: Start ConsumableCooldown timer → set bCanUseConsumables = false
|
||||
└─ On timer end → set bCanUseConsumables = true
|
||||
Step 10: Return true
|
||||
```
|
||||
|
||||
**Nodes Used:** `Branch`, `GetItemAtSlot`, `IsValid`, `Switch on E_ItemType`, `ApplyHealing`, `RestoreStamina`, `RemoveStress`, `Call ApplyBuff`, `Set Timer by Event`
|
||||
|
||||
#### `ApplyBuff(BuffTag: GameplayTag, Duration: Float, Stat: E_PlayerStat, SourceItem: DA_ItemData)` → `void`
|
||||
|
||||
```
|
||||
[Function: ApplyBuff]
|
||||
Step 1: Create S_ActiveBuff struct:
|
||||
- BuffTag = input tag
|
||||
- RemainingDuration = Duration
|
||||
- BuffData = SourceItem
|
||||
- AffectedStat = Stat
|
||||
Step 2: Check if buff with same BuffTag already in ActiveBuffs:
|
||||
- If yes: update RemainingDuration (refresh)
|
||||
- If no: Add to ActiveBuffs array
|
||||
Step 3: Apply stat modification:
|
||||
- Switch on AffectedStat:
|
||||
- Health: NOT here (buffs are temporary, not direct heal)
|
||||
- Stamina: Get BPC_StaminaSystem → Call BlockRegen(0) or similar (buff handles in tick)
|
||||
- Speed: Get BPC_MovementStateSystem → Call ApplyMovementPenalty(1.0 + buffAmount, Duration)
|
||||
- Stress: Get BPC_StressSystem → Call AddStressSource(...)
|
||||
- Damage: Store as damage multiplier (read during damage calc)
|
||||
Step 4: Fire OnBuffApplied(BuffTag, Duration)
|
||||
```
|
||||
|
||||
#### `RemoveBuff(BuffTag: GameplayTag)` → `void`
|
||||
|
||||
```
|
||||
[Function: RemoveBuff]
|
||||
Step 1: Find buff in ActiveBuffs by BuffTag → ForEachLoop with Break
|
||||
Step 2: If found:
|
||||
- Remove from array
|
||||
- Reverse any active stat modification
|
||||
- Fire OnBuffExpired(BuffTag)
|
||||
```
|
||||
|
||||
#### `TickBuffs` → `void` *(Timer callback, runs every 0.1s)*
|
||||
|
||||
```
|
||||
[Function: TickBuffs]
|
||||
Step 1: ForEach ActiveBuffs (iterate backwards if removing):
|
||||
- RemainingDuration -= 0.1
|
||||
- Branch on RemainingDuration <= 0:
|
||||
- True → Call RemoveBuff(BuffTag)
|
||||
Step 2: If ActiveBuffs is empty after cleanup: stop the timer (optional)
|
||||
```
|
||||
|
||||
#### `GetActiveBuffs` → `Array<S_ActiveBuff>`
|
||||
```
|
||||
[Function: GetActiveBuffs] (Pure)
|
||||
└─ Return ActiveBuffs array
|
||||
```
|
||||
|
||||
#### `HasBuff(BuffTag: GameplayTag)` → `Boolean`
|
||||
```
|
||||
[Function: HasBuff] (Pure)
|
||||
Step 1: ForEach ActiveBuffs:
|
||||
- If ActiveBuffs[i].BuffTag == BuffTag → Return true
|
||||
Step 2: Return false
|
||||
```
|
||||
|
||||
### 8.4 Event Dispatcher Bindings
|
||||
|
||||
| Bind to Dispatcher | Custom Event | Logic |
|
||||
|-------------------|-------------|-------|
|
||||
| `BPC_InventorySystem.OnItemUsed` | `OnInventoryItemUsedHandler(Item, Instigator)` | Check ItemData.ItemType == Consumable → Call UseConsumable(SlotIndex) |
|
||||
|
||||
### 8.5 Networking
|
||||
|
||||
| Variable | Replication | Notes |
|
||||
|----------|-------------|-------|
|
||||
| `ActiveBuffs` | `Replicated Using OnRep_ActiveBuffs` | OnRep reapplies visual effects |
|
||||
| `bCanUseConsumables` | `Replicated` | Server controls cooldown |
|
||||
|
||||
**Server RPC:** `Server_UseConsumable(SlotIndex)` — Client calls, server validates item exists/cooldown, applies effects.
|
||||
|
||||
### 8.6 Blueprint Build Checklist
|
||||
|
||||
- [ ] Create BPC_ConsumableSystem component
|
||||
- [ ] Add ConsumableCooldown, ActiveBuffs, bCanUseConsumables variables
|
||||
- [ ] Define S_ActiveBuff struct in the component
|
||||
- [ ] Implement UseConsumable with effect routing to Health/Stamina/Stress/Movement
|
||||
- [ ] Implement ApplyBuff / RemoveBuff with ActiveBuffs array management
|
||||
- [ ] Create TickBuffs timer (0.1s loop) for buff duration countdown
|
||||
- [ ] Bind to BPC_InventorySystem.OnItemUsed
|
||||
- [ ] Add networking: Replicated ActiveBuffs, Server_UseConsumable RPC
|
||||
@@ -147,3 +147,204 @@ Base class for all weapon actors (ranged and melee). Provides common weapon life
|
||||
|
||||
### 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.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
@@ -156,3 +156,207 @@ Central brain for enemy AI characters. Manages perception, decision-making via B
|
||||
- All decision values (ranges, thresholds, speeds) come from data asset
|
||||
- Renamed from `BPC_AIControllerBase` to `AI_BaseAgentController` per Master naming convention.
|
||||
- Cross-references updated: `BPC_PerceptionComponent` → `BPC_AIPerceptionSystem`, `BPC_BehaviorTreeManager` → `BB_AgentBoard`, `BPC_HealthComponent` → `BPC_HealthSystem`.
|
||||
|
||||
---
|
||||
|
||||
## Manual Implementation Guide
|
||||
|
||||
### Class Setup
|
||||
1. Create Blueprint Class: Parent = `AIController`, Name = `AI_BaseAgentController`
|
||||
2. Save to: `Content/Framework/AI/`
|
||||
3. In Class Defaults: set `Auto Possess AI` = `Placed in World or Spawned`
|
||||
|
||||
### Variables (Add to Class Defaults)
|
||||
|
||||
| Variable | Type | Default | Instance Editable |
|
||||
|----------|------|---------|-------------------|
|
||||
| `AIProfile` | `DA_AIProfile` | None | ✓ |
|
||||
| `PossessedEnemy` | `BP_EnemyBase` (Object Ref) | None | |
|
||||
| `BlackboardComp` | `Blackboard Component` (Object Ref) | None | |
|
||||
| `BehaviorTreeComp` | `Behavior Tree Component` (Object Ref) | None | |
|
||||
| `PerceptionComp` | `BPC_AIPerceptionSystem` (Object Ref) | None | |
|
||||
| `StateMachine` | `BPC_AIStateMachine` (Object Ref) | None | |
|
||||
| `AlertSystem` | `BPC_AlertSystem` (Object Ref) | None | |
|
||||
| `bIsActive` | `Boolean` | `true` | ✓ |
|
||||
| `AggressionRange` | `Float` | `1500.0` | ✓ |
|
||||
| `SuspicionRange` | `Float` | `3000.0` | ✓ |
|
||||
| `CombatRange` | `Float` | `800.0` | ✓ |
|
||||
| `HomeLocation` | `Vector` | `(0,0,0)` | |
|
||||
| `LastKnownPlayerLocation` | `Vector` | `(0,0,0)` | |
|
||||
| `LastKnownPlayerLocation` | `Vector` | `(0,0,0)` | |
|
||||
| `bHasLineOfSight` | `Boolean` | `false` | |
|
||||
| `LostPlayerTimer` | `Float` | `0.0` | |
|
||||
|
||||
### Function Implementations
|
||||
|
||||
#### `Event OnPossess(Pawn: Pawn)`
|
||||
|
||||
```
|
||||
[Event OnPossess]
|
||||
Step 1: Call Parent OnPossess
|
||||
Step 2: Cast Pawn to BP_EnemyBase → Set PossessedEnemy
|
||||
Step 3: Get AIProfile from PossessedEnemy (or a spawner data)
|
||||
Step 4: Get Blackboard Component → Set BlackboardComp
|
||||
Step 5: Get Behavior Tree Component → Set BehaviorTreeComp
|
||||
Step 6: Get Component by Class (BPC_AIPerceptionSystem) → Set PerceptionComp
|
||||
└─ If not found on Pawn: Create and attach dynamically
|
||||
Step 7: Get Component by Class (BPC_AIStateMachine) → Set StateMachine
|
||||
Step 8: Get Component by Class (BPC_AlertSystem) → Set AlertSystem
|
||||
Step 9: Set HomeLocation = Pawn.GetActorLocation()
|
||||
Step 10: Set Blackboard value "SelfActor" to Self
|
||||
Step 11: Set Blackboard value "HomeLocation" to HomeLocation
|
||||
Step 12: Set Blackboard value "AIState" to EAIState::Patrol
|
||||
Step 13: Run Behavior Tree (AIProfile.BehaviorTree)
|
||||
Step 14: PerceptionComp.Initialize(AIProfile.PerceptionConfig)
|
||||
Step 15: StateMachine.Initialize(EAIState::Patrol)
|
||||
Step 16: AlertSystem.Initialize()
|
||||
```
|
||||
|
||||
**Nodes:** `Cast To BP_EnemyBase`, `Get Blackboard`, `Set Value as Object/Vector/Enum`, `Run Behavior Tree`, `Create Component (if needed)`, `Get Actor Location`
|
||||
|
||||
#### `Event OnUnPossess(Pawn: Pawn)`
|
||||
|
||||
```
|
||||
[Event OnUnPossess]
|
||||
Step 1: Stop Behavior Tree
|
||||
Step 2: Clear Blackboard values (TargetActor = None, AIState = Disabled)
|
||||
Step 3: PerceptionComp.Deinitialize()
|
||||
Step 4: Call Parent OnUnPossess
|
||||
```
|
||||
|
||||
#### `UpdatePerception(Stimulus: AIStimulus)` → `void`
|
||||
|
||||
*This is called by BPC_AIPerceptionSystem dispatcher when any sense triggers.*
|
||||
|
||||
```
|
||||
[Function: UpdatePerception]
|
||||
Step 1: Branch on Stimulus.WasSuccessfullySensed()
|
||||
False → Return (ignore failed perception)
|
||||
|
||||
Step 2: Switch on Stimulus.Type:
|
||||
Case Sight:
|
||||
Step 2a: Set LastKnownPlayerLocation = Stimulus.StimulusLocation
|
||||
Step 2b: AlertSystem.RaiseAlert(SightAlertValue from AIProfile)
|
||||
Step 2c: Branch on AlertSystem.AlertLevel >= AIProfile.CombatThreshold:
|
||||
True:
|
||||
- SetTarget(Stimulus.StimulusLocation → find closest Actor at that location)
|
||||
- SetAIState(EAIState::Combat)
|
||||
- Set Blackboard "bHasLOS" = true
|
||||
False:
|
||||
- SetAIState(EAIState::Suspicious)
|
||||
- Set Blackboard "StimulusLocation" = Stimulus.StimulusLocation
|
||||
- Set Blackboard "bIsInvestigating" = true
|
||||
|
||||
Case Hearing:
|
||||
Step 3a: AlertSystem.RaiseAlert(HearingAlertValue from AIProfile)
|
||||
Step 3b: StartInvestigation(Stimulus.StimulusLocation)
|
||||
Step 3c: SetAIState(EAIState::Searching)
|
||||
Step 3d: Set Blackboard "StimulusLocation" = Stimulus.StimulusLocation
|
||||
|
||||
Case Damage:
|
||||
Step 4a: SetTarget(Stimulus.StimulusLocation → find instigator)
|
||||
Step 4b: AlertSystem.RaiseAlert(MaxAlertValue)
|
||||
Step 4c: SetAIState(EAIState::Combat)
|
||||
Step 4d: Call RequestReinforcements() if team-aware
|
||||
|
||||
Step 5: Fire OnTargetAcquired(Stimulus.StimulusLocation nearest Actor) if target found
|
||||
```
|
||||
|
||||
**Nodes:** `Switch on EAIPerceptionSense`, `RaiseAlert`, `Set Blackboard Value`, `Branch`, `Find Nearest Actor` or `Get Actor at Location`
|
||||
|
||||
#### `SetAIState(NewState: EAIState)` → `void`
|
||||
|
||||
```
|
||||
[Function: SetAIState]
|
||||
Step 1: Get old state from Blackboard "AIState"
|
||||
Step 2: If NewState == OldState → Return
|
||||
Step 3: Set Blackboard "AIState" = NewState
|
||||
Step 4: Call StateMachine.SetState(NewState)
|
||||
Step 5: Fire OnAIStateChanged(OldState, NewState)
|
||||
Step 6: If NewState == Combat: Call RequestReinforcements()
|
||||
```
|
||||
|
||||
#### `SetTarget(Target: Actor)` → `void`
|
||||
|
||||
```
|
||||
[Function: SetTarget]
|
||||
Step 1: Set Blackboard "TargetActor" = Target
|
||||
Step 2: If Target is valid:
|
||||
- Set Blackboard "TargetLocation" = Target.GetActorLocation()
|
||||
- SetFocus(Target)
|
||||
- Fire OnTargetAcquired(Target)
|
||||
Else:
|
||||
- ClearFocus()
|
||||
- Fire OnTargetLost()
|
||||
```
|
||||
|
||||
#### `StartInvestigation(Location: Vector)` → `void`
|
||||
|
||||
```
|
||||
[Function: StartInvestigation]
|
||||
Step 1: Set Blackboard "bIsInvestigating" = true
|
||||
Step 2: Set Blackboard "TargetLocation" = Location
|
||||
Step 3: Call AI MoveTo(Location)
|
||||
Step 4: On Move Completed:
|
||||
- If target not found at location:
|
||||
- Set Blackboard "bIsInvestigating" = false
|
||||
- ReturnToPatrol()
|
||||
```
|
||||
|
||||
#### `RequestReinforcements()` → `void`
|
||||
|
||||
```
|
||||
[Function: RequestReinforcements]
|
||||
Step 1: Get all AI_BaseAgentController in radius (ReinforcementRange from AIProfile)
|
||||
Step 2: ForEach nearby AI:
|
||||
- If AI.StateMachine.CurrentState == Patrol OR Suspicious:
|
||||
- Call AI.SetTarget(Self.GetBlackboard("TargetActor"))
|
||||
- Call AI.SetAIState(Alerted)
|
||||
Step 3: Fire OnReinforcementRequested(Self.GetActorLocation())
|
||||
```
|
||||
|
||||
**Nodes:** `Get All Actors of Class (AI_BaseAgentController)`, `ForEachLoop`, `Get Distance To`, `Branch`, `Call SetTarget/SetAIState on other AI`
|
||||
|
||||
#### `LostSightOfTarget()` → `void`
|
||||
|
||||
```
|
||||
[Function: LostSightOfTarget]
|
||||
Step 1: Set Blackboard "bHasLOS" = false
|
||||
Step 2: Start LostPlayerTimer (timer loops 0.1s)
|
||||
└─ Each tick: LostPlayerTimer += 0.1
|
||||
Step 3: Branch on LostPlayerTimer >= AIProfile.LostTargetTimeout:
|
||||
True:
|
||||
- ClearTarget()
|
||||
- SetAIState(EAIState::Searching)
|
||||
- StartInvestigation(LastKnownPlayerLocation)
|
||||
- Clear LostPlayerTimer
|
||||
False: continue waiting
|
||||
```
|
||||
|
||||
#### `CanSeeTarget()` → `Boolean`
|
||||
|
||||
```
|
||||
[Function: CanSeeTarget] (Pure)
|
||||
Step 1: TargetActor = Get Blackboard "TargetActor"
|
||||
Step 2: If TargetActor NOT valid → Return false
|
||||
Step 3: Line Trace by Channel from Self location to TargetActor location
|
||||
- Trace channel: Visibility
|
||||
- Ignore Self
|
||||
Step 4: Return (Hit Actor == TargetActor) — true if nothing blocks line of sight
|
||||
```
|
||||
|
||||
### Blueprint Build Checklist
|
||||
|
||||
- [ ] Create AI_BaseAgentController (Parent: AIController)
|
||||
- [ ] Add all variables from the table above
|
||||
- [ ] Create Blackboard asset: BB_AgentBoard with all key names
|
||||
- [ ] Configure Behavior Tree asset (or use placeholder)
|
||||
- [ ] Implement OnPossess: cache components, init perception/state/alert, run BT
|
||||
- [ ] Implement UpdatePerception: route Sight/Hearing/Damage to correct states
|
||||
- [ ] Implement SetAIState with blackboard update and dispatcher
|
||||
- [ ] Implement SetTarget/ClearTarget with blackboard sync
|
||||
- [ ] Implement StartInvestigation with AI MoveTo
|
||||
- [ ] Implement RequestReinforcements (nearby AI coordination)
|
||||
- [ ] Implement LostSightOfTarget with timeout → search
|
||||
- [ ] Implement CanSeeTarget with line trace
|
||||
- [ ] Create BP_EnemyBase child classes that use this controller
|
||||
@@ -1,7 +1,9 @@
|
||||
# Blueprint Spec Template
|
||||
# Blueprint Spec Template v2.0
|
||||
|
||||
Use this template for every system file in `docs/blueprints/`. Replace all `{{placeholders}}` with system-specific values.
|
||||
|
||||
**v2.0 Changes:** Added Section 11 (Manual Implementation Guide) and Section 12 (Build Checklist) for human implementers building Blueprints manually in UE5. Each function now has node-by-node logic with specific UE5 Blueprint node names.
|
||||
|
||||
---
|
||||
|
||||
# {{System Number}} — {{System Name}} (`{{AssetType}}_{{Name}}`)
|
||||
@@ -161,4 +163,109 @@ flowchart TD
|
||||
|
||||
---
|
||||
|
||||
*Template version 1.0 — Reference file for all docs/blueprints/ specifications.*
|
||||
## 11. Manual Implementation Guide
|
||||
|
||||
> **This section is for a human implementer building the Blueprint manually in UE5.**
|
||||
>
|
||||
> Follow these steps in order. Each function is broken down into specific UE5 Blueprint nodes.
|
||||
> Variable names in `code font` refer to variables defined in Section 3.
|
||||
> References to other systems (e.g., `BPC_HealthSystem`) mean "get the component and call its function."
|
||||
|
||||
### 11.1 Class Setup
|
||||
|
||||
1. Create a new Blueprint Class:
|
||||
- Parent Class: `{{ParentClass}}`
|
||||
- Name: `{{AssetType}}_{{Name}}`
|
||||
- Path: `Content/Framework/{{Category}}/`
|
||||
2. Add all variables from Section 3 to the Class Defaults.
|
||||
- Configuration variables: set `Instance Editable` ✓ and `Expose on Spawn` ✓ (if marked).
|
||||
- Internal variables: set to `Private` (no expose).
|
||||
3. If the class implements interfaces, add them in `Class Settings → Implemented Interfaces`.
|
||||
|
||||
### 11.2 Variable Initialization (Construction Script / BeginPlay)
|
||||
|
||||
```
|
||||
Event BeginPlay
|
||||
├─ Set {{VarName}} = {{Default}} // For each internal variable with a default
|
||||
├─ Get Owner → Cast to {{ExpectedOwnerType}} → Store as CachedOwner
|
||||
├─ Get Component by Class ({{RequiredComponent}}) → Store reference
|
||||
│ └─ If NOT valid → Print Warning: "{{Component}} missing on {{Owner}}"
|
||||
├─ [If replicating] Check HasAuthority → if server, initialize replicated vars
|
||||
└─ Fire initialization-related dispatchers
|
||||
```
|
||||
|
||||
### 11.3 Function Implementations
|
||||
|
||||
#### `{{FunctionName}}`
|
||||
|
||||
**Input Pins:** `{{Param1}}` ({{Type1}}), `{{Param2}}` ({{Type2}})
|
||||
**Output Pins:** `{{ReturnValue}}` ({{ReturnType}})
|
||||
|
||||
**Node-by-Node Logic:**
|
||||
```
|
||||
[Function: {{FunctionName}}]
|
||||
Step 1: {{First thing to do — get a reference, check a condition}}
|
||||
Step 2: Branch on {{Condition}}
|
||||
True →
|
||||
Step 2a: {{Action for true branch}}
|
||||
Step 2b: {{Next action}}
|
||||
False →
|
||||
Step 2c: {{Action for false branch}}
|
||||
Step 3: {{Continuation after branch}}
|
||||
Step 4: Fire dispatcher: Call {{OnEventName}}({{Params}})
|
||||
Step 5: Return {{ReturnValue}}
|
||||
```
|
||||
|
||||
**Nodes Used:** {{List of UE5 Blueprint nodes the implementer should search for}}
|
||||
|
||||
**Things to Watch:**
|
||||
- {{Gotcha 1}}
|
||||
- {{Gotcha 2}}
|
||||
|
||||
#### `{{NextFunction}}`
|
||||
|
||||
*(Repeat the same detailed format for every public and protected function)*
|
||||
|
||||
### 11.4 Event Dispatcher Bindings
|
||||
|
||||
List every dispatcher this system binds TO (inbound listeners) and what to do:
|
||||
|
||||
| Bind to Dispatcher (on which system) | Custom Event to Create | What it Does |
|
||||
|--------------------------------------|------------------------|--------------|
|
||||
| `{{Component}}.On{{EventName}}` | `On{{EventName}}Handler` | {{Brief logic}} |
|
||||
|
||||
### 11.5 Networking Setup (if applicable)
|
||||
|
||||
- In `Class Settings`, enable `Replicates` ✓
|
||||
- For each replicated variable, set `Replication` to `Replicated` or `Replicated Using OnRep_{{VarName}}`
|
||||
- Create `OnRep_{{VarName}}` functions that fire the same dispatchers as single-player
|
||||
- Add `Switch HasAuthority` before all state-changing logic
|
||||
- Add `Run on Server` RPC functions with `Server_` prefix
|
||||
|
||||
### 11.6 Quick Node Reference
|
||||
|
||||
Common UE5 Blueprint nodes used in this system:
|
||||
| Node | Where to Find | Used For |
|
||||
|------|---------------|----------|
|
||||
| `{{NodeName}}` | Right-click → "{{search term}}" | {{Purpose}} |
|
||||
|
||||
---
|
||||
|
||||
## 12. Blueprint Build Checklist
|
||||
|
||||
Complete these steps in order when implementing this system:
|
||||
|
||||
- [ ] Create Blueprint class with correct parent
|
||||
- [ ] Add all variables with correct types and defaults
|
||||
- [ ] Implement interface functions (if any)
|
||||
- [ ] Build `BeginPlay` / `OnPossess` / initialization event
|
||||
- [ ] Implement each function from Section 4 following the step-by-step guide
|
||||
- [ ] Create all event dispatchers from Section 5
|
||||
- [ ] Bind to inbound dispatchers (Section 11.4)
|
||||
- [ ] Add networking logic (HasAuthority gates, RPCs, RepNotify)
|
||||
- [ ] Test with validation checklist (Section 9)
|
||||
- [ ] Place in level or attach to character as appropriate
|
||||
|
||||
---
|
||||
|
||||
*Template version 2.0 — Includes Manual Implementation Guide for human implementers.*
|
||||
@@ -184,10 +184,10 @@ docs/developer/
|
||||
|
||||
| Aspect | Blueprint Spec (`docs/blueprints/`) | Developer Reference (`docs/developer/`) |
|
||||
|--------|--------------------------------------|----------------------------------------|
|
||||
| **Purpose** | Define what to build (contract) | Explain how it works (understanding) |
|
||||
| **Audience** | Implementers following a spec | Anyone needing to understand internals |
|
||||
| **Content** | Enums, structs, variables, functions | Data flow, state machines, design rationale |
|
||||
| **Updates** | When design changes | When implementation details change |
|
||||
| **Purpose** | Define what to build with node-by-node logic (v2.0) | Explain how it works (understanding) |
|
||||
| **Audience** | Implementers building Blueprints manually | Anyone needing to understand internals |
|
||||
| **Content** | Enums, structs, variables, functions, **Manual Implementation Guide** | Data flow, state machines, design rationale |
|
||||
| **Format** | TEMPLATE.md v2.0 — includes Build Checklist | Per-category reference docs |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user