Forum rules - please read before posting.

Interactions to Include Additional Interactions Only if Item is Active Item

Hi,

Our game uses "hotspot the interaction". Essentially, what we want is for one or more special interactions to appear only if a certain item has been selected/the cursor has changed to an inventory icon. Right now, we are just able to do "Use Shovel on Rock", for instance, when the rock is the active item/cursor. We'd like to expand the regular interaction for the hotspot (say "Look" and "Take", which should remain in the menu), so that such default non-inventory interactions remain, but also add a number of interactions specific to the item that is the currently selected one.

For instance, we would like the default rock interaction menu when you click on the rock with nothing except the main cursor to be "Look at Rock", "Take Rock".

The rock interaction menu when you have a shovel as the active item/cursor, we would like to be "Look at Rock", "Take Rock", "Smash Rock with Shovel", "Dig Up Rock with Shovel". The two first options would work the same as if you had no active item.

Would the active item mechanism still be the best one to solve for situations like these?

Sel

Comments

  • You'd have to rely on some custom scripting, since Hotspot <-> Inventory interactions are limited to Use/Give, rather than an arbitrary amount.

    The best way that I can think is to treat them as regular Hotspot "Use" interactions, and show/hide/rename them while the Inventory item is active.

    First add the additional verbs Smash / Dig Up as interactions in your Cursor Manager, then add them to your Hotspot as regular Use interactions, and finally add them as new Interaction elements in your Interaction menu.

    Then, attach the following script to your Hotspot and configure its Inspector:

    using UnityEngine;
    using AC;
    
    public class HoldToSelectHotspot : MonoBehaviour
    {
    
        public string itemName = "Shovel";
        public int[] dynamicInteractionIDs;
    
        private void OnEnable ()
        {
            EventManager.OnHotspotSelect += OnSelect;
        }
    
        private void OnDisable ()
        {
            EventManager.OnHotspotSelect -= OnSelect;
        }
    
        private void OnSelect (Hotspot hotspot)
        {
            if (hotspot == GetComponent <Hotspot>())
            {
                bool itemIsActive = (KickStarter.runtimeInventory.SelectedItem != null && KickStarter.runtimeInventory.SelectedItem.label == itemName);
                foreach (int ID in dynamicInteractionIDs)
                {
                    AC.Button button = hotspot.GetUseButton (ID);
                    if (button != null)
                    {
                        button.isDisabled = !itemIsActive;
                    }
                }
    
            }
        }
    
    }
    

    The "Dynamic Interaction IDs" array should contain the IDs of the new Interaction icons. This script will enable/disable those Interactions automatically based on whether or not the item "Shovel" is currently selected.

    Renaming the Interaction element's label will be a bit more tricky, so let's focus on the above first. Give it a try and see how it goes.

  • Hi Chris,
    I still seem to be having problems. I've tried what you suggested, and have two issues.

    1. When clicking on the hotspot without any active item, I still seem to get the two "shovel only" options, regardless of putting their ids in the script.

    2. When clicking on the hotspot with the shovel, it follows from the label text that it seems to be defaulting to "use shovel on rock", with no radial menu appearing upon click at all. This could be some setting that I have active in the settings section but I can't figure out which.

    Sel

  • Apologies - looks like I didn't think that answer through enough.

    When you click on a Hotspot with an inventory item selected, it'll always default to a combine Interaction - a menu will only appear while no item is selected.

    What we could try is to script the enabling of such menu automatically in the event of an inventory interaction. I'll have a look into this.

  • Thanks for the help and looking into it, Chris. It would appear as though point 2 above is also the only one still left to make this work (The first problem was user error - wrong ID specified).

  • OK, give this a go:

    using UnityEngine;
    using AC;
    using System.Collections;
    
    public class ExtraInvInteractions : MonoBehaviour
    {
    
        public int[] dynamicInteractionIDs;
        public int itemID;
        private Hotspot hotspot;
        private string itemLabel;
    
    
        private void OnEnable ()
        {
            hotspot = GetComponent <Hotspot>();
            SetDynamicButtonStates (false);
    
            EventManager.OnHotspotInteract += OnHotspotInteract;
            EventManager.OnMenuTurnOff += OnMenuTurnOff;
            EventManager.OnRequestMenuElementHotspotLabel += OnRequestMenuElementHotspotLabel;
        }
    
    
        private void OnDisable ()
        {
            EventManager.OnHotspotInteract -= OnHotspotInteract;
            EventManager.OnMenuTurnOff -= OnMenuTurnOff;
            EventManager.OnRequestMenuElementHotspotLabel -= OnRequestMenuElementHotspotLabel;
        }
    
    
        private void OnHotspotInteract (Hotspot _hotspot, Button _button)
        {
            if (hotspot == _hotspot)
            {
                bool usedItem = (hotspot.GetButtonInteractionType (_button) == HotspotInteractionType.Inventory && _button.invID == itemID);
                SetDynamicButtonStates (usedItem);
    
                if (usedItem)
                {
                    StartCoroutine (ShowInventoryInteractions ());
                }
            }
        }
    
    
        private void OnMenuTurnOff (Menu menu, bool isInstant)
        {
            if (menu.title == "Interaction")
            {
                SetDynamicButtonStates (false);
            }
        }
    
    
        private string OnRequestMenuElementHotspotLabel (Menu menu, MenuElement menuElement, int slot, int language)
        {
            if (menuElement is MenuInteraction)
            { 
                MenuInteraction menuInteraction = (MenuInteraction) menuElement;
    
                foreach (int ID in dynamicInteractionIDs)
                {
                    if (menuInteraction.iconID == ID)
                    {
                        return KickStarter.cursorManager.GetLabelFromID (ID, language) + " " + menu.TargetHotspot.GetName (language) + " with " + itemLabel;
                    }
                }
            }
            return string.Empty;
        }
    
    
        private IEnumerator ShowInventoryInteractions ()
        {
            yield return null;
            KickStarter.playerMenus.EnableInteractionMenus (hotspot);
            KickStarter.runtimeInventory.SelectItemByID (itemID);
            itemLabel = KickStarter.runtimeInventory.SelectedItem.GetLabel (Options.GetLanguage ());
        }
    
    
        private void SetDynamicButtonStates (bool state)
        {
            foreach (int ID in dynamicInteractionIDs)
            {
                Button button = hotspot.GetUseButton (ID);
                if (button != null)
                {
                    button.isDisabled = !state;
                }
            }
        }
    
    }
    
  • Hey Chris,

    It seems as though OnHotspotInteraction turns out to always have the _button null referenced. Not sure if that is the reason, but subsequently

    bool usedItem = (hotspot.GetButtonInteractionType (_button) == HotspotInteractionType.Inventory && _button.invID == itemID);

    seems to always turn out false for me, which means that if (useditem) -> ShowInventoryInteractions never gets triggered, and I still get the typical "Use X on X" only when using the inv item on the hotspot.

    But I could well be missing something, I'll keep trying in case it's once again user error.

    Selene

  • To update, after looking at the script some more, it is possible that my attempt at diagnosis is somewhat inaccurate.

    But in either event, the problem that remains for me is that despite putting in the proper dynamic IDs corresponding to the two interactions that should be allowed if the shovel is carried, I still end up simply with "use shovel on hotspot" when clicking with the shovel icon on the hotspot in question.

    The two specific interactions are, however, correctly disabled at the start of the game where the shovel is not selected, and they remain disabled when the shovel is in fact picked as the active item.

  • You'll need to define an Inventory interaction between the Hotspot and the item - but without an ActionList assigned.

    To remove the "Use X on Y", go to your Cursor Manager and change the When Inventory selected option to Change Cursor.

  • Almost there, thanks for your patience. It all seems to work now except the label. The line

    itemLabel = KickStarter.runtimeInventory.SelectedItem.GetLabel (Options.GetLanguage ());

    ...throws a null reference exception when the hotspot is clicked with the inventory item in question. It appears that I'm not successfully producing a "selected item" by this method that is not null. KickStarter.runtimeInventory.SelectItemByID (itemID) also seems to produce null, but the itemID that comes in is 0 which is correct (an item that you "carry on start").

    The resulting hotspot label is currently "Dig rock with", with nothing after "with".

    On a related note, is there any straightforward way to make these totally custom, let's say "throw apple AGAINST cliffside, put widget INSIDE box" or similar? For instance, through "override use syntax", that ties into this whole method?

    Selene

  • ...throws a null reference exception when the hotspot is clicked with the inventory item in question

    The SelectItemByID call before it should simply re-select the same item that was used - I can't see why that would fail, unless the item isn't actually present in the Player's inventory.

    Try unchecking Defined interactions deselect active item? in your Settings Manager, which should prevent the need to call SelectItemByID in the first place.

    is there any straightforward way to make these totally custom, let's say "throw apple AGAINST cliffside, put widget INSIDE box" or similar?

    You can override the use syntax in an Inventory Item's properties, but that applies to all Hotspots and only for one interaction type, so it'll always be "Throw applie against (Hotspot)".

    For full control over the line per-Hotspot, you need to hook into the OnRequestMenuElementHotspotLabel event and return the corrected label.

  • Hi Chris,

    It all works now (although I need to turn Define interactions deselect active items? ON rather than OFF to make it all work - it was OFF before. Not sure why?)

    I've encountered an issue while testing this but it seems not to be related to this "special interaction" issue so I've posted about it separately.

    Thanks for the help so far.

    Selene

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.