Page MenuHomeFeedback Tracker

CharacterControllerComponent::TakeGadgetInLeftHand edge case on same frame take to hand as pickup
Confirmed Internally, NormalPublic

Description

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.

Details

Severity
Minor
Resolution
Open
Reproducibility
Always
Operating System
Windows 10 x64
Category
General

Event Timeline

Arkensor created this task.Nov 4 2022, 4:53 PM
Geez changed the task status from New to Confirmed Internally.Nov 7 2022, 9:14 AM