Forum rules - please read before posting.

Override interaction label on a per-hotspot basis

Hello everyone!
Does anyone know if it's possible to override the name of an interaction in a certain hotspot?

I'll explain with a simple scenario: Let's say you have a generic "Use" interaction set up under the Cursors tab in AC Game Editor and you have set the "Prefix cursor labels?" option
When you select use as your Interaction (I have my game set to "Select hotspot then interaction" but I reckon it would be similar with the other modes) your cursor will say "Use hotspot" when you hover a hotspot interaction

It would be cool if there was a way to specify that a certain hotspot-interaction combo should have a different label, so for example if you're selecting "Use" on an NPC the label will say "Push NPC" instead of "Use NPC", similar to how Curse of Monkey Island used to associate different verbs to it's 3 icons

The only way I can think of doing this is cloning the "use" action and assign it to that hotspot, but it's a bit clunky because it would require updating the interaction menu to include every single variant (and also clutter the interactions in the game) while simply overriding the verb in a specific interaction would be much simpler

Comments

  • Verbs and interactions are tied together. If you wanted to associate the Interaction with a different Verb, it would need to be set in the Hotspot's Inspector.

    It is, however, possible to override the Hotspot's label through custom script when over a given Menu element, by way of hooking into the OnRequestMenuElementHotspotLabel event hook.

    Are you referring to the Interaction menu? This script, attached to the Hotspot and its Inspector filled it, ought to do it:

    using UnityEngine;
    using AC;
    
    public class ReplaceVerb : MonoBehaviour
    {
    
        public string replacementVerb = "Push";
        public Hotspot hotspot;
    
        void OnEnable() => EventManager.OnRequestMenuElementHotspotLabel += OnRequestMenuElementHotspotLabel;
        void OnDisable() => EventManager.OnRequestMenuElementHotspotLabel -= OnRequestMenuElementHotspotLabel;
    
        string OnRequestMenuElementHotspotLabel(AC.Menu menu, MenuElement element, int _slot, int language)
        {
            if (menu.title == "Interaction" && element.title == "Use" && KickStarter.playerInteraction.GetActiveHotspot() == hotspot)
            {
                return replacementVerb + " " + hotspot.GetName(Options.GetLanguage());
            }
            return string.Empty;
        }
    
    }
    
  • @ChrisIceBox yeah the script does exactly what I was looking for!
    I think it could be useful if that was done natively in AC, like for example adding an option "Override interaction verb" right under "Enabled" here in the inspector

    https://d.pr/i/SB2Lby

    But the script works fine! I'll probably try to fine tune it so it can obtain the hotspot automatically but it was a HUGE help!

  • edited November 7

    @ChrisIceBox sorry to bump this but I realized there's a small issue with the script

    I noticed it stopped working despite me not updating AC or Unity and after a little debugging I pinpointed the cause to the fact that I also have the same script attached to my player (it has a hotspot so that the second player can interact with them) so the hotspot check was failing because it was checking against my player character's hotspot instead that the one it was supposed to

    In general it doesn't seem like the script as it is right now works if there's multiple instances of it, I'm trying to figure out if I can fix it right now

    EDIT: Sadly I don't think I'm familiar enough with the inner workings of AC to figure this one out, all I can tell is that there only seems to be one OnRequestMenuElementHotspotLabel event active at the same time so the script will only work with whatever script is loaded last and every other hotspot will fail the check and display "Use"

    I suppose one way to fix it would be to have a single replacer per scene that holds a map of Hotspot > Replacement verbs, if such a thing is even possible in Unity

    I think I did it!

    using UnityEngine;
    using AC;
    using System.Collections.Generic;
    
    public class ReplaceVerbs : MonoBehaviour
    {
        void OnEnable() => EventManager.OnRequestMenuElementHotspotLabel += OnRequestMenuElementHotspotLabel;
        void OnDisable() => EventManager.OnRequestMenuElementHotspotLabel -= OnRequestMenuElementHotspotLabel;
    
        [System.Serializable]
        public class HotspotEntry
        {
            public string replacementVerb;
            public Hotspot hotspot;
        }
    
        [Header("Replace Use for Hotspots")]
        public List<HotspotEntry> hotspotList = new List<HotspotEntry>();
    
        private Dictionary<Hotspot, string> hotspotMap;
    
        void Awake()
        {
            BuildDictionary();
        }
    
        void BuildDictionary()
        {
            hotspotMap = new Dictionary<Hotspot, string>();
    
            foreach (var entry in hotspotList)
            {
                if (!string.IsNullOrEmpty(entry.replacementVerb) && entry.hotspot != null)
                {
                    if (!hotspotMap.ContainsKey(entry.hotspot))
                        hotspotMap.Add(entry.hotspot, entry.replacementVerb);
                    else
                        Debug.LogWarning($"Duplicate hotspot '{entry.hotspot.name}' in hotspot list!");
                }
            }
        }
    
        string OnRequestMenuElementHotspotLabel(AC.Menu menu, MenuElement element, int _slot, int language)
        {
            if (hotspotMap == null)
                BuildDictionary();
    
            if (hotspotMap.TryGetValue(KickStarter.playerInteraction.GetActiveHotspot(), out string replacementVerb))
            if (menu.title == "Interaction" && element.title == "Use" && replacementVerb != null)
            {
                Debug.Log("Replacing Use with " + replacementVerb);
                return replacementVerb + " " + KickStarter.playerInteraction.GetActiveHotspot().GetName(Options.GetLanguage());
            }
            return string.Empty;
        }
    }
    

    This lets me create a list for hotspots in every scene that I can check against and replace the Use verb on

    There's just one piece of the puzzle missing, I want to make sure my player characters also have their replacement verbs, how would I go about getting a reference to my player's hotspot (which I understand is instantiated from prefabs)? Can I fetch it using the ConstantID system?

    EDIT: Yep, that worked!

    Hotspot  playerOneHotspot = ConstantID.GetComponent<Hotspot>(PLAYER_ONE_CONSTANT_ID);
    hotspotMap.Add(playerOneHotspot, "Test");
    

    That was easier than I thought! Thanks for putting up such an extensive and flexible scripting system

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.