Weapons · Updated May 22, 2026
Shotgun
Pump-action shotgun in the style of Halo's M90. Fires a spread of 8 pellets per blast.
Pump-action shotgun in the style of Halo's M90. Fires a spread of 8 pellets per blast. Multi-pellet fire is powered by PelletCount on FSLWeaponFireMode — all existing weapons default to 1 and are unaffected.
#How Multi-Pellet Fire Works
PelletCount was added to FSLWeaponFireMode (default 1). In USLGameplayAbility_Fire::ExecuteFire:
- Cosmetics, fire cue, and ammo decrement — fire once per trigger pull, outside the pellet loop
- Trace loop — runs
PelletCounttimes; each iteration callsComputeFireDirectionindependently, producing a fresh random direction withinBulletConeAngleDegrees
- Listen server host — N damage traces, one impact cue execution per pellet that hits
- Remote client — N
FSLShotInfoentries queued toServer_ProcessShots; server validates each pellet independently with its sweep radius forgiveness
Single-pellet weapons (PelletCount = 1) are completely unchanged — the loop runs once with identical behaviour to before.
#Data Asset — DA_SL_Shotgun
Location: Content/SystemLink/Weapons/Shotgun/DA_SL_Shotgun
#Primary Fire Mode
| Field | Value | Notes |
|---|---|---|
bEnabled | ✓ | |
FireType | Hitscan | |
FireMode | SingleShot | One blast per trigger press |
PelletCount | 8 | 8 independent traces per blast |
BulletConeAngleDegrees | 5.0 | Half-angle — ~10° total spread cone |
MaxBulletConeAngleDegrees | 6.5 | Slight extra spread while moving |
MaxBulletSpreadSpeed | 400.0 | Full extra spread at walking speed |
RoundsPerMinute | 0 | Irrelevant for SingleShot |
PostFireDelay | 0.8 | Ability stays alive 0.8s after the blast — drives pump animation via bIsFiring |
MaxAmmo | 60 | No reload — pickups refill CurrentAmmo directly, clamped to this value |
BaseDamage | 12.0 | Per pellet — 96 max at point blank (8×12) |
MaxRange | 3000.0 | Effective range ~20m; drops off fast |
MuzzleSocketName | MuzzleFlash | Match socket name on the shotgun FP mesh |
AmmoDecrementEffect | GE_SL_AmmoDecrement | Same GE as the AR — decrements by 1 per blast |
FireCueTag | GameplayCues.Weapon.Shotgun.PrimaryFire | Muzzle blast + shell eject |
StopFireCueTag | (leave empty) | No looping sound to stop |
ImpactCueTag | GameplayCues.Weapon.Shotgun.Impact | Per-pellet impact — sparks, surface mark |
RecoilPitchKick | 3.5 | Heavy upward kick per blast |
RecoilYawRange | 0.8 | Slight random yaw per blast |
RecoilRecoverySpeed | 5.0 | Slower recovery than AR (pump feel) |
RecoilMaxAccumulation | 10.0 |
#Equip Fields
| Field | Value |
|---|---|
EquipAbilityClass | BP_GA_SL_TP_Shotgun_Equip |
FPEquipAbilityClass | BP_GA_SL_FP_Shotgun_Equip |
EquipCueTag | GameplayCues.Weapon.Shotgun.Equip |
#Pump Delay
PostFireDelay = 0.8 on DA_SL_Shotgun's primary fire mode keeps the fire ability alive for 0.8s after the blast. During that window SLTags.States.Weapon.Firing is on the ASC → bIsFiring is true → the anim blueprint drives the pump animation. The ability ends automatically when the timer expires.
Re-fire is blocked by Activation Blocked Tags = SLTags.States.Weapon.Firing on BP_GA_SL_Shotgun_PrimaryFire — the ability cannot re-activate while the tag is present. No cooldown GE required.
#Gameplay Tags to Register
Add these in Project Settings → GameplayTags before creating cue Blueprints:
GameplayCues.Weapon.Shotgun.PrimaryFire
GameplayCues.Weapon.Shotgun.Impact
GameplayCues.Weapon.Shotgun.Equip
SLTags.Abilities.Equip.ThirdPerson.Shotgun ← trigger tag for TP equip ability
SLTags.Abilities.Equip.FirstPerson.Shotgun ← trigger tag for FP equip ability
All are ini tags (Project Settings → GameplayTags). Same FirstPerson/ThirdPerson pattern as the AR.
#Assets to Create
| Asset | Location | Source | Notes |
|---|---|---|---|
DA_SL_Shotgun | Content/SystemLink/Weapons/Shotgun/ | New data asset (USLWeaponDataAsset) | Fill with values above |
BP_WeaponActor_Shotgun | Content/SystemLink/Weapons/Shotgun/ | Duplicate BP_WeaponActor_AssaultRifle | Point WeaponData → DA_SL_Shotgun |
BP_GA_SL_TP_Shotgun_Equip | Content/SystemLink/AbilitySystem/Abilities/Weapons/Shotgun/ | Duplicate BP_GA_SL_TP_AssultRifle_Equip | Trigger tag → SLTags.Abilities.Equip.ThirdPerson.Shotgun (full CDO setup below) |
BP_GA_SL_FP_Shotgun_Equip | Content/SystemLink/AbilitySystem/Abilities/Weapons/Shotgun/ | Duplicate BP_GA_SL_FP_AssultRifle_Equip | Trigger tag → SLTags.Abilities.Equip.FirstPerson.Shotgun (full CDO setup below) |
BP_GA_SL_Shotgun_PrimaryFire | Content/SystemLink/AbilitySystem/Abilities/Weapons/Shotgun/ | Duplicate BP_GA_SL_AssualtRifle_PrimaryFire | No cooldown GE — pump delay is driven by PostFireDelay on the data asset. Set Activation Blocked Tags = SLTags.States.Weapon.Firing (full CDO setup below) |
GC_SL_Shotgun_PrimaryFire | Content/SystemLink/AbilitySystem/Cues/Weapons/Shotgun/ | Duplicate GC_SL_AssaultRifle_PrimaryFire | Tag → GameplayCues.Weapon.Shotgun.PrimaryFire; wide muzzle flash |
GC_SL_Shotgun_Impact | Content/SystemLink/AbilitySystem/Cues/Weapons/Shotgun/ | Duplicate GC_SL_AssaultRifle_Impact | Tag → GameplayCues.Weapon.Shotgun.Impact |
GC_SL_Shotgun_Equip | Content/SystemLink/AbilitySystem/Cues/Weapons/Shotgun/ | Duplicate GC_SL_AssaultRifle_Equip | Tag → GameplayCues.Weapon.Shotgun.Equip |
BP_SL_WeaponPickup_Shotgun | Content/SystemLink/Pickups/Weapons/Shotgun/ | Duplicate AR pickup | Point WeaponActorClass → BP_WeaponActor_Shotgun |
#Equip Ability — Tag Setup
Both equip ability duplicates need their trigger tag updated. The TP ability is the coordinator:
BP_GA_SL_TP_Shotgun_Equip CDO:
AbilityTags = SLTags.Abilities.Equip.ThirdPerson.Shotgun
ActivationOwnedTags = SLTags.States.Weapon.Equipping
Triggers[0].TriggerTag = SLTags.Abilities.Equip.ThirdPerson.Shotgun
Triggers[0].Source = GameplayEvent
BP_GA_SL_FP_Shotgun_Equip CDO:
AbilityTags = SLTags.Abilities.Equip.FirstPerson.Shotgun
Triggers[0].TriggerTag = SLTags.Abilities.Equip.FirstPerson.Shotgun
Triggers[0].Source = GameplayEvent
The TP equip ability fires the FP trigger via GetEquipTagFromAbilityClass → SendGameplayEvent (same pattern as the AR equip ability — no changes needed to the internal logic, just the tags).
#Fire Ability — BP_GA_SL_Shotgun_PrimaryFire
Duplicate BP_GA_SL_AssualtRifle_PrimaryFire. Changes needed:
- AbilityTags →
SLTags.Abilities.PrimaryFire(same as AR — both respond to the same fire event)
- Activation Owned Tags →
SLTags.States.Weapon.Firing
- Activation Blocked Tags →
SLTags.States.Weapon.Firing(blocks refire during the 0.8s pump delay)
bIsPrimaryFire= true (inherited default, no change needed)
No cooldown GE needed — pump delay is driven by PostFireDelay = 0.8 on the data asset.
OnLocallyPredictedShotFired — implement to play the blast sound and muzzle flash locally.
OnProjectileHitPredicted — fires once per pellet that hits. For a shotgun that means up to 8 invocations per blast for the local player and up to 8 invocations for the listen-server host (the host has no predicted-impact replication path; this BP event is the only way it sees impact FX). If multiple pellets cluster on the same surface, naive impact decal spawning will pile up — dedupe by impact location, throttle decals, or clamp the per-blast count if you need a cleaner look.
#Damage Feel — Tuning Notes
- Point blank (all 8 pellets): 8 × 12 = 96 damage — nearly kills a full-health player in one shot
- Mid range (4 pellets hit): 4 × 12 = 48 — solid chip damage
- Long range (1–2 pellets): 12–24 — tickle damage, rewards range management
- Increase
BaseDamageto 15 for one-shot-kill potential at close range (120 total); lower to 10 for a more forgiving feel (80 total)
BulletConeAngleDegrees = 5°is a tight spread — increase to7–8°for a wider, more forgiving cone
#Build Order
- Register gameplay tags
- Create data asset
DA_SL_Shotgunwith values above (setPostFireDelay = 0.8)
- Create weapon actor BP → point to data asset
- Duplicate and update equip ability BPs (update tags only)
- Duplicate and update fire ability BP (set Activation Owned Tags + Activation Blocked Tags)
- Create cue Blueprints (
GC_assets) with correct tags
- Create pickup BP
- Place shotgun pickup in TestMap
- Test: fire blast, count impacts, verify ammo decrements by 1 per blast, verify pump delay blocks rapid fire
#Test Checklist
#Single-player / gameplay correctness
- [ ] Fire blast → 8 separate impact cues fire on hit surfaces
- [ ] Ammo decrements by 1 per blast (not 8)
- [ ] Pump cooldown prevents firing again for ~0.8s
- [ ] Recoil kicks up noticeably per blast
- [ ] Cycle weapon swaps to/from shotgun correctly with ammo preserved
- [ ] Pickup replaces equipped weapon when inventory full
- [ ] Shotgun drops on death with correct ammo count
#Multiplayer correctness (run Docs/FireAbilityNetworkTesting.md)
- [ ] Test 1 — no
OnLocallyPredictedShotFired/OnWeaponFiredBP events fire on the server for remote players
- [ ] Test 2 — predicted impacts never spawn through walls (channel parity)
- [ ] Test 3 — one
Server_ProcessShotsRPC per blast, not 8 (and AR full-auto unchanged)
- [ ] Dying mid-pump cleanly tears down the fire ability (no lingering
States.Weapon.Firingtag)
- [ ] Local player hears/sees muzzle flash exactly once per blast (cue BP correctly skips locally-controlled instigator)