Weapons · Updated May 22, 2026

System Link — New Weapon Checklist

System Link — New Weapon Checklist

End-to-end steps for adding a new weapon to SystemLink. Follow in order — earlier steps unlock later ones (e.g. native tags must exist before the GAS ability BPs can pick them).

The Assault Rifle is the canonical reference. When in doubt about a property value or asset layout, duplicate the AR's equivalent and customize.

Naming convention: all assets use <Prefix>_SL_<WeaponName>_<Detail> (e.g. BP_GA_SL_Shotgun_PrimaryFire, DA_SL_Shotgun). Weapon-specific assets live under Content/SystemLink/Weapons/<WeaponName>/.

#1. Native Gameplay Tags

Add new tags before anything else — every later step references them.

#In Plugins/SystemLinkCore/Source/SystemLinkCore/Private/GameplayTags/SLTags.cpp

Per-weapon ability tags (paired with the equip ability BPs):


UE_DEFINE_GAMEPLAY_TAG(FirstPerson_<WeaponName>, "SLTags.Abilities.Equip.FirstPerson.<WeaponName>");

UE_DEFINE_GAMEPLAY_TAG(ThirdPerson_<WeaponName>, "SLTags.Abilities.Equip.ThirdPerson.<WeaponName>");

#In Config/DefaultGameplayTags.ini

Cue tags (used by the fire/impact gameplay cues). These don't need C++ declarations — just register them in the ini:


+GameplayTagList=(Tag="GameplayCues.Weapon.<WeaponName>.PrimaryFire")

+GameplayTagList=(Tag="GameplayCues.Weapon.<WeaponName>.Impact")

Add a StopFireCue tag too if the weapon has looping fire effects (rare — only full-auto weapons with sustained loops).


#2. Mesh Assets

#Skeletal Meshes

  • FP mesh (SK_<WeaponName>_FP) — first-person view, usually a stylized cleaner pose
  • TP mesh (SK_<WeaponName>) — third-person, full-detail, viewed by other players

Both rigged to a skeleton that supports the IK + animation conventions used elsewhere in the project. The AR's skeleton is the reference — if your weapon's anatomy is similar, share the skeleton; if not, duplicate and modify.

#Required Sockets

Socket NameOn MeshPurpose
MuzzleFlashFP and TP meshSpawn location for muzzle flash, fire cue, hit traces
AttachPointFP and TP meshWhere the character hand grips the weapon (matches AttachSocketName on FSLWeaponSkeletalMeshData)
Left-hand IK socket (named per-weapon)FP and TP meshWhere the character's left hand grips for IK — LeftHandIKEffectorSocketName in mesh data
Left-hand IK joint target (optional)FP and TP meshPole-vector reference for the IK chain — LeftHandIKJointTargetSocketName
ShellEjectSocket (optional)TP meshShell ejection spawn point (only weapons with visible casings)

Verify the MuzzleFlash socket's +X axis points down the barrel — if rotated 90° off, the TP fire cue and trace origin will be wrong. (This was the shotgun bug fixed mid-shotgun-branch.)


#3. Weapon Data Asset

DA_SL_<WeaponName> (class: USLWeaponDataAsset) under Content/SystemLink/Weapons/<WeaponName>/. The single most important asset — all per-weapon config lives here.

#First/Third Person Mesh Data — FSLWeaponSkeletalMeshData (two instances)

FieldNotes
WeaponMeshThe skeletal mesh asset for this view
AttachSocketNameHand-bone socket on the character mesh (typically hand_r)
RightHandBoneNameReference bone for left-hand IK BoneSpace (typically hand_r)
LeftHandIKEffectorSocketNameSocket on the weapon mesh used as left-hand target
LeftHandIKJointTargetSocketNameOptional pole-vector reference socket
LeftHandIKAlpha0–1, blend strength of the left-hand IK
AnimLayerClassAnim layer linked into the character mesh's ABP (arm pose, IK)
WeaponMeshAnimClassStandalone ABP set directly on the weapon mesh (bolt cycle, pump, etc.). Null for static weapons.
EquipMontageAnimation montage played on this view's mesh during equip

#Primary Fire Mode — FSLWeaponFireMode

FieldNotes
bEnabledSet true
FireTypeHitscan or Projectile
FireModeFullAuto or SingleShot
RoundsPerMinuteFor full-auto only
PostFireDelaySeconds the ability stays alive after firing — drives pump/bolt animations via bIsFiring. Single-shot only.
BulletConeAngleDegreesHalf-angle of stationary spread
MaxBulletConeAngleDegreesHalf-angle of max-movement spread
MaxBulletSpreadSpeedPlayer speed at which spread reaches max
PelletCountShots per trigger pull (1 for normal, 8+ for shotgun)
MaxAmmoTotal ammo capacity — no reload model, set high enough that reload isn't needed (AR=600, Shotgun=60)
BaseDamagePer-pellet damage
DamageMultipliersPer-body-part multipliers (Body/Head/Arms/Legs). Defaults: 1.0 / 2.0 / 0.75 / 0.75. Override per-weapon if a specific weapon needs different headshot/limb tuning (e.g. Head = 1.5 on shotgun to avoid one-shot kills). See Docs/DamagePipeline.md § 0.
MaxRangeTrace distance in cm
MuzzleSocketNameMust match a socket on the FP and TP mesh
AmmoDecrementEffectGE_SL_AmmoDecrement — reused across all weapons
FireCueTagGameplayCues.Weapon.<WeaponName>.PrimaryFire
StopFireCueTagOptional, for looping fire sounds
ImpactCueTagGameplayCues.Weapon.<WeaponName>.Impact
RecoilPitchKickUpward kick per shot
RecoilYawRangeRandom horizontal kick range
RecoilRecoverySpeedHow fast recoil decays
RecoilKickbackDistancePositional kick on FP viewmodel (cm)
RecoilLateralRangeRandom lateral position kick (cm)

#HUD

FieldNotes
PrimaryReticleClassWBP_SL_Reticle_<WeaponName>
SecondaryReticleClassOnly if the weapon has a secondary fire mode
AmmoWidgetClassWBP_SL_Ammo_<WeaponName>
WeaponIconT_Icon_<WeaponName> texture
WeaponDisplayNameHuman-readable name shown in pickup prompts

#Other

FieldNotes
Equip cue tag (EquipCueTag)Per-weapon equip cue if desired
FP/TP equip ability classesBP_GA_SL_FP_<WeaponName>_Equip, BP_GA_SL_TP_<WeaponName>_Equip
Primary fire ability classBP_GA_SL_<WeaponName>_PrimaryFire

#4. GAS Abilities

Duplicate the AR's abilities and customize. Always BP_GA_SL_<WeaponName>_<Detail> under Content/SystemLink/AbilitySystem/Abilities/Weapons/<WeaponName>/.

#Equip abilities (TP + FP)

  • BP_GA_SL_TP_<WeaponName>_EquipServer Initiated, plays the TP equip montage, sends Equip_Attach event at the right anim frame
  • BP_GA_SL_FP_<WeaponName>_EquipLocal Only, plays the FP equip montage

Set their AbilityTags to the matching native tag from step 1.

#Primary fire ability

  • BP_GA_SL_<WeaponName>_PrimaryFire — duplicate BP_GA_SL_AssualtRifle_PrimaryFire (note the AR typo Assualt — content rename is deferred)
  • AbilityTagsSLTags.Abilities.PrimaryFire
  • Activation Owned TagsSLTags.States.Weapon.Firing
  • Activation Blocked TagsSLTags.States.Weapon.Firing (prevents re-fire during PostFireDelay)
  • Triggers[0]{ TriggerTag: SLTags.Events.Weapon.PrimaryFire, Source: GameplayEvent }
  • Override OnLocallyPredictedShotFired for FP cosmetics (sound, muzzle flash, recoil shake)
  • Override OnProjectileHitPredicted for predicted hit feedback

#5. Gameplay Cues

Duplicate the AR cues and customize. Under Content/SystemLink/AbilitySystem/Cues/Weapons/<WeaponName>/:

  • GC_SL_<WeaponName>_PrimaryFire (GameplayCueNotify_Burst) → muzzle flash Niagara + fire sound, tag: GameplayCues.Weapon.<WeaponName>.PrimaryFire
  • GC_SL_<WeaponName>_Impact (GameplayCueNotify_Burst) → impact spark + decal + sound, tag: GameplayCues.Weapon.<WeaponName>.Impact

GameplayCue notify path is already scanned recursively from Content/SystemLink/AbilitySystem/Cues/ (config in DefaultGame.ini) — no path config needed.

Remember: the fire cue excludes the local instigator by default so the local shooter doesn't double-play their own effects. FP cosmetics come from OnLocallyPredictedShotFired in the fire ability BP.


#6. Animations

For each view (FP and TP):

  • Equip montage — character + weapon mesh, plays on equip. Include an SLAnimNotify_SendGameplayEvent firing SLTags.Events.Weapon.Equip_Attach at the frame the weapon should attach.
  • Idle pose / aim offset — base pose while holding the weapon
  • Fire animation / additive layer — recoil kick, pump cycle, bolt cycle as appropriate

#Anim Blueprints

Two layers of ABP per weapon:

  • Character ABP (ABP_MC_FP_<WeaponName>, ABP_MC_TP_<WeaponName>) — drives the character's hand pose, recoil layer, fire state machine. Use as anim layer via AnimLayerClass on the mesh data.
  • Weapon mesh ABP (optional, set via WeaponMeshAnimClass) — drives bolt cycling, pump animation, or any weapon-mesh-only motion.

#State machine gotchas

  • Non-looping fire animations in a state machine state need "Always Reset on Entry" enabled — otherwise the asset player gets stuck at t=end on first play and never replays. See feedback_animbp_state_reset_on_entry.md memory.
  • Inertial Blend transitions need an Inertialization node downstream in the AnimGraph — otherwise UE warns on quit.

#7. HUD Assets

#Weapon Icon

  1. Open the Weapon Icon Generator editor utility (USLWeaponIconGenerator)
  1. Point at the TP weapon mesh, neutral gray background, transparent background off
  1. Export side-profile render
  1. Feed render + AR icon (as style reference) into Nano Banana with the prompt in Docs/AIPrompts.md
  1. Import result as T_Icon_<WeaponName> in Content/SystemLink/Weapons/<WeaponName>/UI/ (or Icons/)
  1. Assign to WeaponIcon on the data asset

#Ammo Widget

Per the design vision: Doom Eternal-style numeric counter (icon + CurrentAmmo / MaxAmmo). Duplicate WBP_SL_Ammo_AssaultRifle, swap the icon image, save as WBP_SL_Ammo_<WeaponName> in Content/SystemLink/Weapons/<WeaponName>/UI/. No structural changes needed — OnAmmoChanged(int32 CurrentAmmo, int32 MaxAmmo) BIE handles the display.

Set on DA_SL_<WeaponName>.AmmoWidgetClass.

The multi-slot strip (WBP_SL_AmmoStrip) reads AmmoWidgetClass from the data asset and creates one instance per carried weapon slot automatically — no additional HUD wiring is needed when adding a new weapon.

#Reticle Widget

Duplicate WBP_SL_Reticle_AssaultRifle to WBP_SL_Reticle_<WeaponName> in Content/SystemLink/Weapons/<WeaponName>/UI/. Customize the crosshair to reflect the weapon's character — wider for shotgun (pellet spread), tight for precision weapons, etc.

Set on DA_SL_<WeaponName>.PrimaryReticleClass.


#8. Weapon Actor Blueprint (Optional)

If the weapon needs custom logic beyond what ASLWeaponActor provides (e.g. special attach/detach FX, custom drop behavior), create BP_SL_WeaponActor_<WeaponName> deriving from ASLWeaponActor. Otherwise the C++ base class handles everything.


#9. Weapon Pickup Blueprint

BP_SL_WeaponPickup_<WeaponName> deriving from ASLWeaponPickup (or ASLPickupBase for custom pickup logic). Place in Content/SystemLink/Pickups/Weapons/<WeaponName>/. Set WeaponActorClass to the weapon actor class.


#10. Test Checklist (per weapon)

  • [ ] Pickup → carry → equip → fire works without crashes
  • [ ] FP idle and fire animations look correct
  • [ ] TP idle and fire animations replicate to other clients
  • [ ] HUD swaps to the new ammo widget and reticle on equip
  • [ ] Ammo counter decrements on fire, refills on ammo pickup
  • [ ] MaxAmmo cap is respected by pickups
  • [ ] Muzzle flash spawns at the MuzzleFlash socket with correct orientation
  • [ ] Impact effects play on hit
  • [ ] Recoil applies and recovers smoothly
  • [ ] Drop on death works — weapon spawns as a pickup in the world
  • [ ] Multiplayer correctness: see Docs/FireAbilityNetworkTesting.md
  • [ ] No LogAnimation: Setting an additive animation ... is not allowed warnings (check Animation Mode on any preview SkeletalMeshActors)

#Reference Pattern

Assault Rifle is the canonical reference. Every step above has a working AR counterpart:

  • DA_SL_AssaultRifle
  • BP_GA_SL_AssualtRifle_PrimaryFire (typo preserved — content rename deferred)
  • GC_SL_AssaultRifle_PrimaryFire, GC_SL_AssaultRifle_Impact
  • WBP_SL_Ammo_AssaultRifle, WBP_SL_Reticle_AssaultRifle, T_Icon_AssaultRifle
  • ABP_MC_FP_AssaultRifle, ABP_MC_TP_AssaultRifle

When in doubt: duplicate AR, customize the parts that differ.