Now · Updated Jun 16, 2026
Editor Tasks
Things that need to be done in the Unreal Editor. Compile first before opening the editor.
Things that need to be done in the Unreal Editor. Compile first before opening the editor.
When a section here lands, remove it. Past completed work is recorded in Docs/Progress.md under "Completed."
#Sidearm Shooting
Prerequisite: build SystemLinkEditor first — the sidearm fire C++ (active-fire-weapon routing + actor-owned ammo) must be compiled. Detail + rationale: Docs/SidearmMode.md §8.1–8.2.
Minimum to get a shot firing = tasks 1–3.
Tasks 1–4 done via the Unreal MCP bridge on 2026-06-09 (registered tag name is
SLTags.States.Weapon.SidearmActive, not the shorthand below; pistol muzzle socket isMuzzle).
Note: tasks 1–4 edited Blueprint CDOs / data assets through Python + save_asset — if a PIE test
shows stale values, recompile the affected BPs in-editor to be safe. Tasks 5–6 (cosmetics, HUD) remain.
- [x] 1. Create
BP_GA_SL_Pistol_PrimaryFire— duplicateBP_GA_SL_AssualtRifle_PrimaryFire bIsPrimaryFire = true✓RequiredWeaponClass = BP_SL_WeaponActor_Pistol✓ (was still pointing at the AR actor)ActivationRequiredTags = SLTags.States.Weapon.SidearmActive✓ActivationBlockedTags=Dead,Meleeing(inherited from AR dup — kept) ✓ActivationOwnedTags = SLTags.States.Weapon.Firing✓Triggers[0] = { Tag: Events.Weapon.PrimaryFire, Source: GameplayEvent }✓
(parent USLGameplayAbility_Fire). CDO:
- [x] 2. Block primary while sidearm drawn — added
SLTags.States.Weapon.SidearmActiveto
ActivationBlockedTags on BP_GA_SL_AssualtRifle_PrimaryFire and BP_GA_SL_Shotgun_PrimaryFire ✓.
- [x] 3. Grant the ability —
BP_GA_SL_Pistol_PrimaryFireadded toAS_AbilitySet_Default✓.
(Fire abilities for equipped weapons are granted on equip via FireMode.FireAbilityClass; the sidearm is a separate always-carried slot that never runs through GrantWeaponAbilities, so it MUST be granted via the ability set — hence no FireAbilityClass set on DA_SL_Pistol.)
- [x] 4. Sidearm weapon data asset —
DA_SL_Pistol.PrimaryFireModefilled:bEnabled=true,
FireMode=SingleShot, RoundsPerMinute=400, BaseDamage=26, MaxAmmo=12, MuzzleSocketName=Muzzle, DamageMultipliers=defaults. No AmmoDecrementEffect (actor-owned ammo). FireCueTag/ImpactCueTag still empty — see task 5. (Values are tuning placeholders — adjust to taste.)
- [~] 5. Fire cosmetics — partially done (borrowing AR FX) 2026-06-09.
DA_SL_Pistol.PrimaryFireMode.FireCueTag/ImpactCueTagset to the AR cues- Still open: verify the pistol BP's
OnLocallyPredictedShotFiredplays FP muzzle flash + sound
(GameplayCue.Weapon.AssaultRifle.PrimaryFire / .Impact) → observers + impact covered.
for the shooter (the cue excludes the local player). If the AR-duplicate didn't carry it, wire it (reuse AR FP muzzle/sound). Then pistol-specific FX (GC_SL_Pistol_PrimaryFire, own muzzle Niagara + fire sound) as polish.
- [ ] 6. HUD sidearm ammo indicator (separate) — bind
SidearmWeapon->OnAmmoChangedto a fixed
indicator. The C++ already keeps CurrentAmmo correct + replicated; this just displays it.
- [ ] 7. FP fire animations — DECIDED: state-machine, not montages (shotgun pattern). Add a
- C++ tie-in:
DA_SL_Pistol.PrimaryFireMode.PostFireDelayis currently0; aFiringstate needs
Firing state to ABP_FP_Pistol (arm recoil) and ABP_Pistol (gun-mesh slide), gated by the Firing tag / bIsFiring; TP equivalents in ABP_TP_Pistol. Apply shotgun lessons: "Always Reset on Entry" on the non-looping fire state + an Inertialization node downstream (see feedback_animbp_state_reset_on_entry). Beepers authors clips in Maya (none exist yet).
dwell time, so single-shot likely needs PostFireDelay > 0 (shotgun uses it to hold the pump). Set once the fire-clip length is known.
Test (listen server, 2 players): RT alone fires the primary; hold LT then RT fires the sidearm; sidearm ammo drains on its own count; primary ammo untouched while sidearm is out; host sees a client's sidearm shots deal the sidearm's damage (the untested damage-RPC path).