How to properly equip and unequip items via ability

Hi, I have a use case where I want an ability to give a weapon to the player.
I want to use this pattern for all sorts of equipment (grenades, drones, throwing knives, special heavy weapons, ect.) but right now I am trying to get a grenade to work.

I have an ability that calls inventory.AddItemIdentifierAmount() followed by inventory.EquipItem() to grant the player a single use grenade weapon with a 10 second recharge.
When the grenade is used, or if the ability is canceled by pressing the ability key again, I call inventory.UnequipItem() followed by inventory.RemoveCharacterItem() to remove the grenade from the inventory. I then call inventory.EquipItem() with the character's previously equipped item to give them their gun back. This, for the most part, works.

The issue arises when the player tries swap weapons while holding the grenade. If swapping to previous, I can catch the unequipped event and remove the grenade. If swapping to next, there is no unequipped event, and the player shows a "grenade pull out" animation and equips the grenade which they were already equipping... then things break when trying to swap back to the player's gun. (also, when the grenade is initially equipped, the animation does not change. The grenade is held as if it were a rifle, with no pull-out animation or anything. I have immediateEquip set to false.)

I looked more into the inventory, EquipPrevious, EquipNext, and EquipUneuip classes... and I wonder if I am doing this right, and if there is an already established way to accomplish what I'm trying.

Any help would be appriciated.
 
For this situation you should not call inventory.Equip/UnequipItem directly. Instead you should use the ability system and item sets. This page has an example:

 
Got it, the ability equips much better now.
I am still having issues when unequipping the ability-grenade.
My code to restore state and remove the object is as follows:
C#:
if (equipUnequip.ActiveItemSetIndex != previouslyEquippedItemIndex)
                equipUnequip.StartEquipUnequip(previouslyEquippedItemIndex, true);

inventory.RemoveCharacterItem(equippedItem, true);

The primary issue is that if I was at item set index 0 before activating the ability and receiving the item, the character is equipping no item groups after using the grenade, creating a situation where the player cannot change weapons. It seems to work find if I am on index 1...

Is there an established way to clean up single use objects and restore equipped state?

Edit: After slimming down my code (aka rebuilding from scratch with only what I know works, because multiple hours of troubleshooting and experimentation bloated and complicated things) I can confirm that no item group is selected after the player uses the grenade. I suspect it is because the throw animation is still playing when my finished event is fired. Are there some events in inventory, EquipUnequip, or ItemSetManager that I should be listening to in order to make this transition work?

For clarification, the characterItem grenadeWeapon may already be destroyed when this code is being triggered, depending on how Opsive cleans up the FragGrenadeWeapon from the inventory when grenades run out. That said, I would like for this class to handle cleaning up state from both a single deployable which may not exist (like a grenade) as well as slightly more persistent weapons that will need to be removed by script (like a grenade launcher). I don't think this will be a problem, if I understand that RemoveCharacterItem() can fail to remove stuff in such cases... but in case that might be causing some of my problems here, I thought I'd bring it up.

Any guidance on how to accomplish resetting the previous item and removing the used ability-item from the character's inventory will be appreciated.
 
Last edited:
I suspect that it's because of your direct RemoveCharacterItem call to the inventory component. You should instead use the drop ability as it will make sure everything is cleaned up.
 
Yup, that did the trick, thanks!
Two last questions:
1: I would like the to play the equip animation of the grenade (or whatever equipment), but I want to skip the unequip animation of whatever gun the player was holding previously.

At the moment I accomplish this by using equipUnequip to slot 0 (which is empty) with immediate=true, then equipUnequip to the grenade slot normally. This works for now... but I plan on slot 0 having a melee weapon eventually.

Is there any way to reserve/ create an empty slot for this purpose, or otherwise have a hybrid of regular and instant slot swapping?

2: I am currently unable to "drop" the item consistently when the player switches to next-previous item in the item set. If I try to drop it OnUnequip, then Drop.StartAbility() fails to start. If I drop it OnEquip when equipping to some other item, it works unless transitioning to an empty item set.
 
Last edited:
You can set the unequip duration to 0 on the item to prevent the item from playing that animation.

2: I am currently unable to "drop" the item consistently when the player switches to next-previous item in the item set. If I try to drop it OnUnequip, then Drop.StartAbility() fails to start. If I drop it OnEquip when equipping to some other item, it works unless transitioning to an empty item set.
By design the drop ability doesn't work when you are unequipping. We can take a look at this for a future improvement.
 
Gotcha.
I have gotten the drop ability to work consistently by adding a delegate to OnAnimatorItemUnequipCompleteE to drop the item.

I think I have one last issue:
If I equip the item while in slot 0, which has no items in it, the grenade equips. Then I use the grenade and it throws normally.
Then I wait for the ability to recharge and use it again. On this next use, the grenade equips but the "Trajectory Object" script and the models are disabled. When aimed, the trajectory comes up, but it cannot be thrown.

This only happens on the second use of the ability from an item set with no items. If I use from a item set with an item, no issue. If I use from an item set with no items, throw the grenade, then swap from the empty item set to a set with something, then back to the item empty item set before using the ability again, no issues.

I've poked around the source code quite a bit, but I'm not sure what to look for that would be causing this behavior.
Any idea what might be causing this, and how to fix it?
 
Last edited:
Unfortunately that's getting to be a more complex situation so I'm not sure what is going on. On the item action you can enable debugging which may help, but the best method is to insert a breakpoint within the use ability and figure out why the item isn't being used.
 
Yeah, I was hoping that maybe the symptoms (models disabled and inability to fire) would be known and associated with a certain script which I could look into.
Anyways, thanks! This has been very helpful in learning my way around the character controller.

Aside from the one issue, I have this working fairly well (Edit: key spamming also causes issues). Though, I'm sure that an Opsive implementation would be cleaner and more flexible. I know you guys are very busy (thanks again for helping me here), so if you find time I think that a "Grant One-Off item" ability would be valuable. A couple prominent AAA games do stuff like that. The two biggest examples that come to mind are the "Golden Gun" and "lighting staff" in Destiny and many equipment based killstreaks in the Call of Duty franchise.

Of course, if there is an easier way to go about this, then I'm all ears.
 
Last edited:
The inability to throw was caused by the Simple Trigger Action Module. when using the ability a second time, the bool m_WasTriggered was stuck to true (even though the method UseItemTrigger() was never called (at least my breakpoint was not hit)). I fixed it by calling ResetModule() on it when my ability initializes the grenade.

I have not been able to find what script/ method is responsible for the item graphics, which are still not visible, despite the weapon being usable now. I looked in Third Person Object, but did not see anything that would be enabling/disabling the mesh renderer of the items. If you could point me to what script directly controls the mesh renderer of items, I can trace the issue the rest of the way...
 
Last edited:
Glad you are making progress. The SpawnProjectile module has an option to disable the visible object - do you have that module and property enabled?
 
Awesome, patched the issue. Thanks!
My current solution feels a bit hacky, so I will keep my eye out for an Opsive implementation of this type of script if it gets on the roadmap.
(also I would buy the Deathmatch AI kit if it has a script which does single-use items in an ability/ killstreak format).

I think this is resolved, though I may open another question if I cannot figure out how to manage keyspamming. Once again, thanks!
 
Top