When equipping a gadget directly via CharacterControllerComponent::TakeGadgetInLeftHand and enabling bool skipAnimations = true there is an invalid invoke of the CharacterControllerComponent::OnGadgetStateChanged and the gadget is un-equipped by the engine.
Below is a setup to demonstrate this. It adds new storage to the player where on item insertion a gadget is instantly equipped.
modded class SCR_CharacterControllerComponent { //------------------------------------------------------------------------------------------------ override void OnGadgetStateChanged(IEntity gadget, bool isInHand, bool isOnGround) { super.OnGadgetStateChanged(gadget, isInHand, isOnGround); PrintFormat("OnGadgetStateChanged(%1,%2,%3)", gadget, isInHand, isOnGround); } }
[EntityEditorProps(category: "EveronLife/HandCarry", description: "Storage for items that can only be carried in hands", color: "0 0 255 255")] class EL_HandInventoryStorageComponentClass: UniversalInventoryStorageComponentClass { } class EL_HandInventoryStorageComponent : UniversalInventoryStorageComponent { //------------------------------------------------------------------------------------------------ override protected void OnAddedToSlot(IEntity item, int slotID) { super.OnAddedToSlot(item, slotID); PrintFormat("OnAddedToSlot(%1,%2)", item, slotID); CharacterControllerComponent characterController = CharacterControllerComponent.Cast(GetOwner().FindComponent(CharacterControllerComponent)); characterController.TryPlayItemGesture(EItemGesture.EItemGestureNone); characterController.TakeGadgetInLeftHand(item, 1, false, true); // <-------------------- notice the "true" parameter for skip animation here } }
If picking up a pair of binoculars or other gadget items it produces this output
SCRIPT : OnAddedToSlot(<ENTITY HERE>,0)
SCRIPT : OnGadgetStateChanged(<ENTITY HERE>,1,0)
SCRIPT : OnGadgetStateChanged(<ENTITY HERE>,0,0)
There the item is added to the storage and TakeGadgetInLeftHand takes place causing the first OnGadgetStateChanged invoke where the in-hands boolean is correctly set to true.
Afterward, with no stack trace (indicating invoke from the engine-side) another OnGadgetStateChanged event is invoked this time indicating the item was forced out of the hands again.
If not skipping the animation via the true parameter this problem does not occur and the item stays in hands correctly.
This also works when called not from the storage component itself but from the manager's event
modded class SCR_InventoryStorageManagerComponent { //------------------------------------------------------------------------------------------------ override protected void OnItemAdded(BaseInventoryStorageComponent storageOwner, IEntity item) { super.OnItemAdded(storageOwner, item); if (!EL_HandInventoryStorageComponent.Cast(storageOwner)) return; PrintFormat("OnItemAdded(%1)", item); CharacterControllerComponent characterController = CharacterControllerComponent.Cast(storageOwner.GetOwner().FindComponent(CharacterControllerComponent)); characterController.TryPlayItemGesture(EItemGesture.EItemGestureNone); characterController.TakeGadgetInLeftHand(item, 1, false, true); } }
SCRIPT : OnItemAdded(<ENTITY HERE>,0)
SCRIPT : OnGadgetStateChanged(<ENTITY HERE>,1,0)
The issue appears to be related to the bool skipAnimations = true parameter or a combination of timing and this parameter.