gunBase 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 AmmoCount and CurrentGrip.

  • 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.

circle-info

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

On BeginPlay, the weapon first sets AmmoCount from CurrentConfig.TotalAmmoCount.

It then:

  • scans mesh components for SocketLaserAttachment

    • if found, it spawns BP_TFA_Attachment_Laser and attaches it to that socket

  • scans mesh components for SocketGripAttachment

    • if found, it attaches SM_Grip_Attachment to that socket

  • spawns two cosmetic magazines through SpawnMagazine

    • one for SocketMagazineAttachment

    • one for SocketMagazineReserveAttachment

  • hides the reserve magazine by default through SetMagazineVisibility(false, true)


Runtime State and Cosmetic Logic


AmmoCount

AmmoCount 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()

This custom event cycles CurrentGrip through three enum states:

  • NewEnumerator0

    • hides SM_Grip_Attachment

  • NewEnumerator1

    • shows SM_Grip_Attachment

    • assigns CurrentConfig.MeshGripVertical

  • NewEnumerator2

    • shows SM_Grip_Attachment

    • assigns 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:

  • SocketMagazineAttachment

  • SocketMagazineReserveAttachment

  • SocketCasingEject

  • SocketGripAttachment

  • SocketLaserAttachment

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)

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)

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)

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 = false uses SocketMagazineAttachment

  • bIsReserve = true uses SocketMagazineReserveAttachment

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)

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 ImpulseForce with bVelChange = true

  • Angular impulse uses a random axis multiplied by RotationForce with bVelChange = true

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 matters

  • Spin uses a random axis scaled by RotationSpeed with bVelChange = 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 SocketCasingEject transform on the receiver skeleton.

    • Or bias the RotationOffset passed into EjectCasing.

  • Magazine visibility is not working

    • Verify the spawned magazine actors are attached to the same sockets that SetMagazineVisibility checks.

    • Socket name mismatches are the most common cause.

  • Grip mesh is wrong or not visible

    • Verify SocketGripAttachment exists on the mesh component used at runtime.

    • Verify MeshGripVertical and MeshGripAngled are set in the config.

  • Ammo-driven cosmetic behavior looks stuck

    • Check whether another system is driving AmmoCount.

    • This Blueprint resets negative values back to TotalAmmoCount on Tick.



Last updated

Was this helpful?