Equipment / Equipment Handlers

What are equipment handlers?

As the name suggests we use equipment handlers to handle all things related to our equipped equipment. This includes the visual shown on our pawn, as well as any added functionality the equipment may provide. Equipment handlers are added to the pawn automatically when items are equipped, and they are removed when they are unequipped.

We assign our equipment handler to our equipment in our DT_Equipment data table.

The Base Equipment Handler

By default, all equipment either uses, or is based off of, the AC_EquipmentHandler component in the Blueprints/EquipmentHandlers/ folder. This base equipment handler is responsible for the visual state of our equipment. We then inherit from this blueprint to add in our extra functionality, like how our weapons work, or how the rocket backpack launches the player in the air when jumping.

You can use the base handler for any equipment that is just showing a static or skeletal mesh on the pawn. Or, build off of it and treat it as the foundation layer. To make your own custom handler you will make a child of either the base handler, or one of the other provided ones. Then to add in your custom logic you override specific functions integrated into the lifecycle hooks of the base handler.

If you make your own handler, you can override which is associated with a piece of equipment in the DT_Equipment data table.

AC_EquipmentHandler Overrides

onBeforeEquip Called at the start of the equip process.
onEquip Called at the end of the equip process.
onBeforeUnequip Called at the start of the unequip process.
onUnequip Called at the end of the unequip process.
onUnequipClient Called on the client at the very end of the end play event of the equipment handler.
onToggleHidden Called when the equipment visibility changes.
onDynamicDataUpdated Called on initialization, and then any time the data updates while equipped.
onSetupClient Called on the client after initialization. We use this override in some of our other handlers to inject custom inputs and UIs. If you override this function in a child of one of these other handlers the inputs or UIs will stop working if you do not include a call to parent within it.
onAssign Called when the equipment handler receives data about which equipment is using it. Whenever handlers are refreshed this event will be called. The difference between this function and the onDynamicDataUpdated function is that onAssign is called anytime equipment refreshes, not just when data changes.

AC_EquipmentHandler Important Events

EquipmentAction Called when relaying information to the pawn. To add more entries to the equipment action list edit E_EquipmentAction in the Blueprint/Variables/Enums/ folder. ENUM WARNING: It is safe to add items to the enum list but do not rearrange or remove any of the current entries from the enumeration. You can easily break parts of the code that depend on the current values. Make sure you review the values of all current references before making any changes.
HideFor Call to hide the visual of this handler for an amount of time equal to Seconds.

AC_EquipmentHandler Variables

equipShowDelay (Default: 0.2) If we are delaying showing our visual on equip wait for that amount of time then show our visual.
unequipHideDelay (Default: 0.2) If we are delaying hiding our visual on unequip wait for that amount of time then hide our visual.

Simple Logic Handler

The simple logic handler extends our base equipment handler to add an additional input mapping context, it also manages the input actions related to this input mapping context and provides additional events for us to override for both the up and down state of a primary and secondary input action. These events allow us to take advantage of press, release, and hold actions. This IMC_InventorySystemDemo_SimpleHandler input mapping context in the Blueprints/EquipmentHandlers/Weapons/Simple/ folder is added using the onSeutpClient override.

The simple handler is an abstract class, which means you can’t use it directly but instead need to make a child of it and use that instead.

Simple Logic Handler Overrides

onProjectileSpawn Called when a projectile is spawned using the spawnProjectile method. Provides a reference of the projectile actor.
onPrimaryButtonDown Called when the primary button is pressed.
onPrimaryButtonUp Called when the primary button is released.
onSecondaryButtonDown Called when the secondary button is pressed.
onSecondaryButtonUp Called when the secondary button is released.

Simple Logic Handler Added Methods

shootProjectile Call this method to spawn a projectile based on the ProjectileClass variable in your handler. The projectile actor will spawn at the Muzzle socket name on your mesh component if it has one. If it doesn’t it will use a forward vector from the player. We use this method to spawn our grenade example.
getDamage A simple damage calculator that gets the base damage value from your equipped items dynamic data. Also optionally supports a damage.deviation dynamic data variable which is a float of how much to deviate it, and the randomization of the actual damage value. For example if your item has a damage value of 100 and a deviation of 0.2 a damage value will be randomly picked between 80 and 120. You can also provide a damage Multiplier (default 1), a Minimum damage value, and a Chance variable to decide if the damage is an actual hit. When chance fails no damage will return. By default chance is set to 1, which means 100% success rate. If you reduce it to 0.3 you will have a 30% chance to land a hit.

Simple Logic Handler Variables

actionDelayOnEquip The amount of time to wait when equipping before the primary or secondary action can be used.
projectileClass The actor class to use as a projectile when calling the shootProjectile event.
projectileNoSocketDistanceFromPlayer When the socket Muzzle is not found on your mesh component a forward vector from the player is used for the spawning location of projectiles. The value of this integer is the distance (default: 500) from the player.
primaryHoldTime The amount of time the primary button was last held for.
secondaryHoldTime The amount of time the secondary button was last held for.
lastProjectile The reference to the last projectile spawned by this handler.

Simple Logic Extended Handlers

We extend the functionality of our Simple Logic Handler to create the following:

Simple Range Handler

AC_EquipmentHandler_Simple_Range in the Blueprints/EquipmentHandlers/Weapons/Range/ folder is a simple range weapon that shoots a projectile and consumes an ammo item. It uses a custom UI that shows the current and remaining ammo count, and also includes a custom input action for reloading. Both of these assets can be found in the same folder as the simple range equipment handler.

This handler uses the primary action to shoot the weapon, and if the clip is empty, reload it. It uses the right click to tell the pawn it is aiming. The change to the camera occurs inside our pawn when the EquipmentAction event on our event graph receives the Aim Start or Aim Stop actions.

These first few ammo related variables are dynamically set at runtime when the setupAmmo function is called in this handler. It sets the values of these variables based on data pulled from the dynamic data of the equipment item. To set these variables you would set the associated keys in the item’s dynamic data.

ammoItemRowName (dynamic data key: ammo) - Our ammo item row name.
ammoClipMaxSize (dynamic data key: ammo.clipmax) - The max number of ammo per ammo clip. Once spent reloading required.
ammoClipCurrent (dynamic data key: ammo.clip) - The current number of ammo shots left in the ammo clip, updated automatically each shot. If you manually set this dynamic data key the value will be used as the starting ammo already loaded in the clip when the weapon is first picked up. If this value is not found the range weapon will proceed as if the clip is empty, thus needing to be reloaded. Then, once the ammo is loaded this key will be added.

These variables can be set manually in the handler:

ammoUI The UI to show, by default it uses the UI_RangeAmmoClip in the same folder as the handler.
reloadSpeed The duration of time it takes to reload the weapon, by default it is set to 2 seconds.
playerAmmoSources These are the player storage components the range handler will use to look for and consume ammo items. By default it is set to Inventory and then Hotbar. The order of this array directs where the ammo is pulled from first, only when the current source is empty will the next source in the list be used.

Simple Range Automatic Handler - AC_EquipmentHandler_Simple_RangeAutomatic

This handler extends our Simple Range Handler to make the weapon an automatic, allowing us to hold down the primary action to continue firing at a rate defined by the AutomaticRateOfFire variable inside the handler.

Simple Range Automatic Handler (with Extras) - AC_EquipmentHandler_Simple_RangeAutomatic_Extra

This handler extends our automatic range handler by integrating a line trace (lineTraceShoot), and disables the actual projectile. Also offers a way to define the max distance of the line trace using the dynamic data key range. You can also set variables to define a minimum damage (shotMinimumDamage), and shot chance (shotChance). We use this handler for our Pistol and Rifle Lyra clone examples. The customized data for different equipment is driven through dynamic data.

Simple Throwable - AC_EquipmentHandler_Simple_Throw

This handler is an extension of the Simple Handler, and illustrates a way to handle throwables, like grenades. The player charges up a throw by holding down the primary button, then when they release the projectile is hurled.

The distance thrown is based on the hold time, more specifically a percentage based on the amount of time held against the max hold time. You can define the max hold duration, the throw forward and height velocity. If you hold the button for the max duration the full velocity will be used. If you hold the button for less then the max the percentage will be used to determine the velocity.

These variables are available on this handler:

throwMaxHold duration of time to hold in order to reach the maximum velocity.
throwVelocityForward forward momentum of the projectile at the max hold time.
throwVelocityHeight height momentum of the projectile at the max hold time.
throwVelocityMultiplierAn easy way to scale both the forward and height values.
throwUI UI to show when the throwable is equipped.
throwMinimumHoldPerecentage minimum amount of time to hold to initiate a throw. If the hold time is less than this amount, the onThrowMiniumNotMet will be called.

This additional override is added through this handler:

onThrowMinimumNotMet An override to perform custom functionality when the minimum is not met. By default it will initialize the melee primary action on the pawn.

Additional Sample Handlers

AC_EQH_Simple_Throw_Grenade This handler extends our throwable to create our grenade example. The only thing that changes with this blueprint is the projectile class.
AC_EquipmentHandler_Simple_Melee This handler extends our simple handler to create a simple melee primary and secondary attack.
AC_EquipmentHandler_RocketBackpack This handler launches the player into the air when they jump.
AC_EquipmentHandler_Shrinket This handler uses a delegate to control shrinking the pawn when equipped. We use a delegate to control the functionality so when we unequip we can make sure enough time passes so that the scale change replicates.

How to handle Unarmed Attacks

Something like this is a bit out of scope for this asset, and would be better aligned with a combat system. I still want to at least point you down the right path if you are looking to provide a simple functionality and don't mind creating the code yourself. Here is what I suggest:

  1. Create your own input bindings or actions for the primary and secondary attack and place the events somewhere like in your pawn.
  2. When your input events are hit, check to see if the Equipment Stance saved in your pawn is set to your default, which we set as Unarmed by default. This default can be changed on the AC_InventorySystem component we added to our player controller. Browse to the Configuration Equipment section in the details panel of this component and the variable you are looking for is EquipmentDefaultStance.
  3. Only when it is set to Unarmed will you be safe to proceed with your unarmed attack montages and logic.

The most important part about this is checking to make sure the equipment stance is Unarmed.

You wouldn't use an equipment handler for something like this, and it wouldn't be part of the equipment system. Instead you would write your own code to handle it, most likely in the pawn or a component on the pawn. You can still use the equip and animation events on the pawn if you would like, you would just have to call them manually.