Forum rules - please read before posting.

Advice on custom inventory interactivity

Hi!

I'm working on a project, that requires a control scheme a bit different from AC defaults. I want to ask if it's possible to do simple modifications to source code to make this possible, or should I be looking to write a custom input/inventory solution?

Overall it's a context menu based interaction system. Where you click on hotspot, see possible interactions in context menu and choose one. But RMB/LMB buttons are switched.

I was able to accomplish this by disabling "mouse has default functionality" and by assigning InteractionA/B to mouse clicks.

Here are specifically the problematic parts:
1) Switching the RMB/LMB functionality

_LMB on object in inventory - LookAt
RMB on object in Inventory - Take (Object sticks to cursor)
RMB on object in inventory while another object in hand - combine

RMB on empty space in inventory while an object in hand - release object
LMB on object in inventory while another object in hand - LookAt
_

I think this should be possible by switching the Left/Right buttons in menu code?
I tried modifying the "UISlotClick" to something like:

    private void Update ()
    {
        if (menuElement)
        {
            if (KickStarter.playerInput != null && KickStarter.playerInput.InputGetButtonDown ("InteractionB"))
            {
                if (KickStarter.playerMenus.IsEventSystemSelectingObject (gameObject))
                {
                    menuElement.ProcessClick (menu, slot, MouseState.RightClick);
                }
            }
            //CUSTOM_EDIT
            else if (KickStarter.playerInput != null && KickStarter.playerInput.InputGetButtonDown("InteractionA"))
            {
                if (KickStarter.playerMenus.IsEventSystemSelectingObject(gameObject))
                {
                    menuElement.ProcessClick(menu, slot, MouseState.SingleClick);
                }
            }
            //CUSTOM_EDIT
        }

but the item still won't select on right-click. Is item selection handled in menuelement code?

Another point is, even if I switched buttons. Would the Examine item on left click, while another item is currently selected thing work without major code change?

2) "RMB on Hotspot while item is in hands/item is selected - > context menu opens with all base actions incl. "Use item and hotspot with each other""

Is there a way to do this without custom input system?

RMB on Hotspot with guitar in hands - Bring back guitar to car, then go to the Hotspot and open context menu: Look at, Examine, Take (whatever makes sense)

Comments

  • Switching the RMB/LMB functionality

    Sounds like the issue is specific to Unity UI. If you temporarily switch your menu's Source to Adventure Creator, are the swapped inputs working correctly?

    The UISlotClickRight script provides right-click / InteractionB functionality, but left-click comes from the EventSystem's Submit button.

    AC spawns its own EventSystem at runtime, but you can supply your modified one at the top of the Menu Manager - or map the Submit input to mouse 1. Try this instead of the code edit above.

    Would the Examine item on left click, while another item is currently selected thing work without major code change?

    When an item is selected, a right-click (now left-click) on another item will result in the original item being deselected. However, it does sound like this would be a useful option, and I'll consider this further.

    If you want to try something yourself in the meantime, be aware that the click functionality of an InventoryBox element can be completely overridden by custom script. If you set its "Inventory box type" to "Custom Script", you can then hook into the OnMenuElementClick custom event to control what happens when clicking on a given slot, i.e.:

    using UnityEngine;
    using AC;
    
    public class CustomInventory : MonoBehaviour
    {
    
        private void OnEnable () { EventManager.OnMenuElementClick += ElementClick; }
        private void OnDisable () { EventManager.OnMenuElementClick -= ElementClick; }
    
        private void ElementClick (AC.Menu _menu, MenuElement _element, int _slot, int _buttonPressed)
        {
            if (_element is MenuInventoryBox)
            {
                MenuInventoryBox inventoryBox = _element as MenuInventoryBox;
                InvInstance clickedItem = inventoryBox.GetInstance (_slot);
                if (InvInstance.IsValid (clickedItem))
                {
                    if (_buttonPressed == 1)
                    {
                        InvInstance selectedItem = KickStarter.runtimeInventory.SelectedInstance;
                        if (InvInstance.IsValid (selectedItem))
                        {
                            clickedItem.Combine (selectedItem);
                        }
                        else
                        {
                            clickedItem.Select ();
                        }
                    }
                    else if (_buttonPressed == 2)
                    {
                        clickedItem.Examine ();
                    }
                }
                else
                {
                    KickStarter.runtimeInventory.SetNull ();
                }
            }
        }
    
    }
    

    "RMB on Hotspot while item is in hands/item is selected - > context menu opens with all base actions incl. "Use item and hotspot with each other""

    Clicking a Hotspot while an item is selected will always result in the item being used with it.

    However, you could try keeping the Hotspot's inventory interaction disabled by default, and then hook into the OnHotspotInteract event - which will fire anyway - and use this to manually turn on the interaction menu, after re-enabling the inventory interaction.

    Maybe something like this:

    using UnityEngine;
    using AC;
    using System.Collections;
    
    public class DynamicInvInteraction : MonoBehaviour
    {
    
        public int itemID;
        private Hotspot hotspot;
    
    
        private void OnEnable ()
        {
            hotspot = GetComponent <Hotspot>();
            SetDynamicButtonState (false);
    
            EventManager.OnHotspotInteract += OnHotspotInteract;
            EventManager.OnMenuTurnOff += OnMenuTurnOff;
        }
    
    
        private void OnDisable ()
        {
            EventManager.OnHotspotInteract -= OnHotspotInteract;
            EventManager.OnMenuTurnOff -= OnMenuTurnOff;
        }
    
    
        private void OnHotspotInteract (Hotspot _hotspot, AC.Button _button)
        {
            if (hotspot == _hotspot)
            {
                bool usedItem = (hotspot.GetButtonInteractionType (_button) == HotspotInteractionType.UnhandledInventory && _button.invID == itemID);
                SetDynamicButtonState (usedItem);
    
                if (usedItem)
                {
                    StartCoroutine (ShowInventoryInteraction ());
                }
            }
        }
    
    
        private void OnMenuTurnOff (Menu menu, bool isInstant)
        {
            if (menu.title == "Interaction")
            {
                SetDynamicButtonState (false);
            }
        }
    
    
        private IEnumerator ShowInventoryInteraction ()
        {
            yield return null;
            KickStarter.playerMenus.EnableInteractionMenus (hotspot);
            KickStarter.runtimeInventory.SelectItemByID (itemID);
        }
    
    
        private void SetDynamicButtonState (bool state)
        {
            hotspot.GetInvButton (itemID).isDisabled = !state;
        }
    
    }
    

    On this and above, I'd recommend getting the functionality correct with the default inputs (left click use, right click examine etc), since you're dealing with two issues at once otherwise.

    RMB on Hotspot with guitar in hands - Bring back guitar to car, then go to the Hotspot and open context menu: Look at, Examine, Take (whatever makes sense)

    Sorry, I don't follow. Do you mean the Player should physically move somewhere before the Interaction menu is run?

  • Hey, thank you! I will try your suggestions.
    Nevermind about the guitar. I accidentally posted extra entry :D

    One question about overriding the input system, won't that make all the buttons submit on right click? Not just inventory?

  • Yes, it will - good point.

    Though, it may not be necessary to change in retrospect. The CustomInventory script above gives you custom inventory functionality - try just swapping the buttonPressed value checks around so that "2" results in Combine/Selection and "1" results in Examine.

    I'd recommend temporarily switching your Menu's Source to AC - Unity UI may compound the issue - and get it working in there first.

  • edited May 2021

    Hey,
    What I have done is I returned the A/B interactions to default values (LMB = A, RMB = B ). As this approach seems to break the least amount of things.

    I was able to get Inventory working like I wanted with Custom Inventory Script You shared.

    I could use advice on how to switch several other interactions.
    1) Now I need to override Hotspot clicking interactions. So when I right-click hotspot the Interaction menu to open, and similarly if I right-click with the item selected the item on hotspot interaction to run.

    Should I set "See Interactions With" to custom script and use a custom component added to hotspot to listen to hotspot click events? Can I detect Right/Left click with that?

    2) When the interaction menu opens, the one that shows all interactions possible on hotspot. I want to make so both left/right click activate the buttons.

    Would setting inventorybox section to custom and using modified version of "CustomInventory.cs" you shared work? Or does this need to be set to "Hotspot Based" to work?

    Thanks

  • Treating this as a separate problem for the moment: if all you want to do is remap buttons, rather than change the functionality, you can override mouse button detection with a delegate override script.

    See the Manual's "Remapping inputs" chapter for more, but here's a sample script that causes RMB clicks to be read as LMB clicks if either a Hotspot is active, or the Interaction menu is open:

    using UnityEngine;
    using AC;
    
    public class InputOverride : MonoBehaviour
    {
    
        private void Start ()
        {
            KickStarter.playerInput.InputGetMouseButtonDownDelegate = GetMouseButtonDown;
            KickStarter.playerInput.InputGetMouseButtonDelegate = GetMouseButton;
        }
    
        private bool GetMouseButtonDown (int mouseButton)
        {
            if (KickStarter.playerInteraction.GetActiveHotspot () || KickStarter.playerMenus.IsInteractionMenuOn ())
            {
                // Active Hotspot or Interaction menu is open
                if (mouseButton == 0)
                {
                    // Right click counts as left click
                    return Input.GetMouseButtonDown (1);
                }
            }
        }
    
        private bool GetMouseButton (int mouseButton)
        {
            if (KickStarter.playerInteraction.GetActiveHotspot () || KickStarter.playerMenus.IsInteractionMenuOn ())
            {
                // Active Hotspot or Interaction menu is open
                if (mouseButton == 0)
                {
                    // Right click counts as left click
                    return Input.GetMouseButton (1);
                }
            }
        }
    
    }
    

    This is more intended to serve as an example - it may need tweaking to suit your own needs - but try it without any other custom scripts to begin with to see how it works.

  • edited May 2021

    Hey, Something strange is happening with that code.

    So here is my setup. Int A/B have defaults, I tried with and without "Mouse clicks have default functionality"

    and I tried this code:

    What happens is if I have mouse over hotspot, and I right-click the is True is returned for " if (mouseButton == 0)" s if (Input.GetMouseButtonDown(1)) section.

    But when I left click nothing happens.
    The only other custom script I have is on inventory menu.

    What could cause LMB to be ignored and RMB to be read as mouseButton 0 on hotspot? Any other place if I click on ground for example the LMB/RMB are correctly read as 0/1

  • Even if "Mouse clicks have default functionality?" is checked, InteractionA/B inputs are still available as alternatives. Try removing/renaming these from your Input Manager to ensure they don't conflict with the script.

  • edited May 2021

    Thank you! That was what was causing the issue.

  • edited May 2021

    Hello, I've run into another issue with custom scenario.

    Is there a way to stop the pause menu from deselecting the currently selected item?
    Or I guess for a cursor to work properly, I'd need to remember the selected item before the pause menu opens and restore it when it closes to gameplay?

  • You can hook into the OnInventoryDeselect custom event to record which item was last de-selected, but the default Pause menu de-selects the item via its "ActionList when turn on" asset assigned in the Menu Manager. Unassigning this asset from its list of properties should prevent this behaviour.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.