Base Weapon (BP_TFA_BaseWeapon)
Core weapon actor that assembles meshes from config, tracks cosmetic state, and exposes notify-friendly helpers.
Asset path: /Game/InfimaGames/TacticalFPSAnimations/Common/Core/Weapons/BP_TFA_BaseWeapon
BP_TFA_BaseWeapon is the pack’s main weapon actor. It assembles the runtime weapon from CurrentConfig, manages cosmetic props such as magazines, the laser attachment, and the grip mesh, and exposes helper functions that many animation notifies rely on.
Quick Navigation
Weapon Responsibilities
Builds the weapon mesh and attachments from
CurrentConfig.Spawns cosmetic actors such as magazines and the optional laser attachment.
Tracks cosmetic state such as
AmmoCountandCurrentGrip.Exposes notify-friendly helper functions such as magazine visibility, magazine drop, and casing ejection.
Key Properties
CurrentConfig(BP_TFA_BaseConfig)Drives sockets, meshes, montages, and sounds.
CurrentGrip(E_TFA_GripAttachment)Tracks which grip variant is currently active.
AmmoCount(int32)Stores the cosmetic ammo count used by the weapon logic.
SK_Receiver(SkeletalMeshComponent)The main weapon mesh that owns the relevant sockets.
See Base Config (BP_TFA_BaseConfig) for the exact config fields this weapon reads.
Weapon Setup Flow
Construction Script
When CurrentConfig is valid, the Construction Script sets the receiver skeletal mesh from CurrentConfig.MeshReceiver, assigns the weapon AnimBP from CurrentConfig.ABP_Weapon, and attaches optional static meshes through config-defined sockets.
Those optional meshes include:
handguard
silencer
chambered bullet
jammed casing
scope
front sight
rear sight
The script uses AssignNewStaticMesh for these parts. That helper first assigns the new mesh, then attaches the component to the requested parent and socket.
Correct socket names on the weapon skeleton matter a lot here. If a socket name is wrong, the mesh usually still assigns, but it will attach in the wrong place.
BeginPlay
BeginPlayOn BeginPlay, the weapon first sets AmmoCount from CurrentConfig.TotalAmmoCount.
It then:
scans mesh components for
SocketLaserAttachmentif found, it spawns
BP_TFA_Attachment_Laserand attaches it to that socket
scans mesh components for
SocketGripAttachmentif found, it attaches
SM_Grip_Attachmentto that socket
spawns two cosmetic magazines through
SpawnMagazineone for
SocketMagazineAttachmentone for
SocketMagazineReserveAttachment
hides the reserve magazine by default through
SetMagazineVisibility(false, true)
Runtime State and Cosmetic Logic
AmmoCount
AmmoCountAmmoCount is initialized from CurrentConfig.TotalAmmoCount on BeginPlay.
On Tick, the weapon checks whether AmmoCount < 0. If that happens, it resets AmmoCount back to CurrentConfig.TotalAmmoCount. This keeps the cosmetic magazine logic from staying in an invalid state after another shot is triggered while already empty.
RandomizeGripAttachment()
RandomizeGripAttachment()This custom event cycles CurrentGrip through three enum states:
NewEnumerator0hides
SM_Grip_Attachment
NewEnumerator1shows
SM_Grip_Attachmentassigns
CurrentConfig.MeshGripVertical
NewEnumerator2shows
SM_Grip_Attachmentassigns
CurrentConfig.MeshGripAngled
In practice, the event rotates between no grip, vertical grip, and angled grip.
Sockets Used at Runtime
These sockets are read from CurrentConfig and used by the weapon at runtime:
SocketMagazineAttachmentSocketMagazineReserveAttachmentSocketCasingEjectSocketGripAttachmentSocketLaserAttachment
Magazine spawn, magazine drop, and casing ejection depend on socket transforms. If those sockets are missing, the spawned result usually appears to come from the weapon origin.
Grip and laser setup work a little differently. On BeginPlay, the weapon iterates mesh components and only performs the attach or spawn when that component reports the requested socket.
Functions Used by Animation Notifies
AssignNewStaticMesh(Target, Parent, NewMesh, SocketName)
AssignNewStaticMesh(Target, Parent, NewMesh, SocketName)This helper is used heavily by the Construction Script.
It:
sets the target component’s static mesh
attaches that component to the requested parent
snaps the attachment to the requested socket
This is the common path used for the handguard, silencer, chambered bullet, jammed casing, scope, and sights.
SpawnMagazine(Name SocketName)
SpawnMagazine(Name SocketName)This helper spawns BP_TFA_BaseMagazine using CurrentConfig as WeaponConfig, validates the spawned actor, and attaches it to SK_Receiver at the requested socket with snap rules.
BeginPlay uses it twice:
once for the main magazine socket
once for the reserve magazine socket
SetMagazineVisibility(bool bVisible, bool bIsReserve)
SetMagazineVisibility(bool bVisible, bool bIsReserve)This function iterates the child components of SK_Receiver, including descendants, compares each component’s AttachSocketName against the selected magazine socket, and calls SetHiddenInGame(NewHidden = !bVisible, PropagateToChildren = true) on matches.
bIsReserve = falseusesSocketMagazineAttachmentbIsReserve = trueusesSocketMagazineReserveAttachment
In practice, the visibility change is socket-driven. It does not search by component name, and it does not care which child component type is attached as long as it is attached to the right socket.
SpawnDroppedMagazine(float ImpulseForce, float RotationForce)
SpawnDroppedMagazine(float ImpulseForce, float RotationForce)This function spawns BP_TFA_PhysicsMagazine at SK_Receiver.GetSocketTransform(SocketMagazineAttachment, RTS_World), sets the spawned mesh to CurrentConfig.MeshMagazine, assigns ImpactSound = CurrentConfig.SoundCue_WEP_MagDrop, and then applies linear and angular impulse.
Linear impulse uses the magazine socket up vector multiplied by
ImpulseForcewithbVelChange = trueAngular impulse uses a random axis multiplied by
RotationForcewithbVelChange = true
EjectCasing(Rotator RotationOffset, float MinEjectForce, float MaxEjectForce, float RotationSpeed)
EjectCasing(Rotator RotationOffset, float MinEjectForce, float MaxEjectForce, float RotationSpeed)This function spawns BP_TFA_PhysicsCasing at SK_Receiver.GetSocketTransform(SocketCasingEject, RTS_World), assigns ImpactSound = CurrentConfig.SoundCue_WEP_CasingEject when supported, sets the mesh to CurrentConfig.MeshBulletCasing, and applies the casing physics.
Direction comes from the forward vector of
CombineRotators(SocketRotation, RotationOffset)Force uses a random float in
[MinEjectForce, MaxEjectForce]Linear impulse uses
bVelChange = false, so mass still mattersSpin uses a random axis scaled by
RotationSpeedwithbVelChange = true
Lifecycle Notes
On BeginPlay, the weapon already spawns magazine actors for both magazine sockets and hides the reserve magazine. That is why the notify states only need to toggle visibility instead of spawning the props themselves.
The weapon also conditionally spawns or attaches cosmetic parts based on available sockets, including the laser attachment and the grip component.
On Tick, it guards against a negative cosmetic ammo count by restoring AmmoCount from TotalAmmoCount.
See Laser Attachment (BP_TFA_Attachment_Laser) for the laser-specific runtime behavior.
Common Customization Points
Ejection direction feels wrong
Adjust the
SocketCasingEjecttransform on the receiver skeleton.Or bias the
RotationOffsetpassed intoEjectCasing.
Magazine visibility is not working
Verify the spawned magazine actors are attached to the same sockets that
SetMagazineVisibilitychecks.Socket name mismatches are the most common cause.
Grip mesh is wrong or not visible
Verify
SocketGripAttachmentexists on the mesh component used at runtime.Verify
MeshGripVerticalandMeshGripAngledare set in the config.
Ammo-driven cosmetic behavior looks stuck
Check whether another system is driving
AmmoCount.This Blueprint resets negative values back to
TotalAmmoCountonTick.
Related Blueprints
Last updated
Was this helpful?

