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 is Muzzle).
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 — duplicate BP_GA_SL_AssualtRifle_PrimaryFire
  • (parent USLGameplayAbility_Fire). CDO:

    • 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 }
  • [x] 2. Block primary while sidearm drawn — added SLTags.States.Weapon.SidearmActive to
  • ActivationBlockedTags on BP_GA_SL_AssualtRifle_PrimaryFire and BP_GA_SL_Shotgun_PrimaryFire ✓.

  • [x] 3. Grant the abilityBP_GA_SL_Pistol_PrimaryFire added to AS_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 assetDA_SL_Pistol.PrimaryFireMode filled: 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 cosmeticspartially done (borrowing AR FX) 2026-06-09.
    • DA_SL_Pistol.PrimaryFireMode.FireCueTag/ImpactCueTag set to the AR cues
    • (GameplayCue.Weapon.AssaultRifle.PrimaryFire / .Impact) → observers + impact covered.

    • Still open: verify the pistol BP's OnLocallyPredictedShotFired plays FP muzzle flash + sound
    • 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->OnAmmoChanged to a fixed
  • indicator. The C++ already keeps CurrentAmmo correct + replicated; this just displays it.

  • [ ] 7. FP fire animationsDECIDED: state-machine, not montages (shotgun pattern). Add a
  • 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).

    • C++ tie-in: DA_SL_Pistol.PrimaryFireMode.PostFireDelay is currently 0; a Firing state needs
    • 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).