Forum rules - please read before posting.

Checking where the items in an interaction are stored

Is it possible to have an action to check where the items in an interaction are currently stored? Example: if I use a battery on a torch in the inventory, my actionlist would remove both the battery and the torch from the inventory and add a new powered torch item to it. If the items are in a container, though, I'd like to remove both items from the container instead and add the powered torch to the container. I would also need to check for other permutations, like selecting the battery from the inventory and clicking on the torch in the container.

«1

Comments

  • Checking where an item is would only be half the solution - you'd still need to update the item inside the container, since the Inventory: Add or remove Action only deals with items that are held by the Player.

    You could feasibly do this with Container: Add or remove, but you'd have to cater for all possibilities. The easiest way to deal with this situation would be to rely on a custom script that updates the items according to where they are.

    The OnInventoryCombine_Alt custom event is triggered when two items are used together, and includes the instances in its parameters. The InvInstance class has a GetSource function that can be used to determine which collection an item is stored in, which you can then modify accordingly:

    using AC;
    using UnityEngine;
    
    public class DynamicReplaceItem : MonoBehaviour
    {
    
        private string itemAName = "ItemA";
        private string itemBName = "ItemB";
        private string newItemName = "ItemC";
    
        private void OnEnable () { EventManager.OnInventoryCombine_Alt += OnInventoryCombine; }
        private void OnDisable () { EventManager.OnInventoryCombine_Alt -= OnInventoryCombine; }
    
        private void OnInventoryCombine (InvInstance invInstanceA, InvInstance invInstanceB)
        {
            // Check if item names match
            if ((invInstanceA.InvItem.label == itemAName && invInstanceB.InvItem.label == itemBName) || 
                (invInstanceB.InvItem.label == itemAName && invInstanceA.InvItem.label == itemAName))
            {
                // Delete Item A
                InvCollection collectionA = invInstanceA.GetSource ();
                collectionA.Delete (invInstanceA);
    
                // Get the index of Item B
                InvCollection collectionB = invInstanceB.GetSource ();
                int indexB = collectionB.IndexOf (invInstanceB);
    
                // Insert Item C
                InvInstance newInvInstance = new InvInstance (newItemName);
                collectionB.Insert (newInvInstance, indexB);
    
                // Delete item B
                collectionB.Delete (invInstanceB);
            }
        }
    
    }
    
  • This looks excellent, thank you! I'll give it a try once I manage to fix the editor slowdown issue on the other thread.

  • edited February 2021

    OK, I tested this, and I think we are almost there! Just a few issues to fix.

    First of all, my setup: items can be reordered in menus, and the selected item's display is set to "hide from menu". Most items have "can carry multiple?" unchecked. The ones that do have that option checked always have a slot capacity of 1. My inventory menu has a "Icons only" display type, and "Clear content" when the slot is empty. My container has a "Select Item Only" click behaviour, display type of "Icon Only", and "Clear content" when slot is empty.

    Now on to the issues:

    (1) The code you provided has a bug: if ItemA is in your inventory, and you click on it, take it to an empty container slot and place it there, and then click on it again to remove it and once again place it on the same slot, that item will be deleted. This can be fixed by having two if statements instead of one:

    using AC;
    using UnityEngine;
    
    public class DynamicReplaceItem : MonoBehaviour
    {
    
        private string itemAName = "ItemA";
        private string itemBName = "ItemB";
        private string newItemName = "ItemC";
    
        private void OnEnable() { EventManager.OnInventoryCombine_Alt += OnInventoryCombine; }
        private void OnDisable() { EventManager.OnInventoryCombine_Alt -= OnInventoryCombine; }
    
        private void OnInventoryCombine(InvInstance invInstanceA, InvInstance invInstanceB)
        {
    
             // Check if item names match
             if (invInstanceA.InvItem.label == itemAName && invInstanceB.InvItem.label == itemBName)
            {
                // Delete Item A
                InvCollection collectionA = invInstanceA.GetSource();
                collectionA.Delete(invInstanceA);
    
                // Get the index of Item B
                InvCollection collectionB = invInstanceB.GetSource();
                int indexB = collectionB.IndexOf(invInstanceB);
    
                // Insert Item C
                InvInstance newInvInstance = new InvInstance(newItemName);
                collectionB.Insert(newInvInstance, indexB);
    
                // Delete item B
                collectionB.Delete(invInstanceB);
            }
    
            // Check if item names match
            if (invInstanceA.InvItem.label == itemBName && invInstanceB.InvItem.label == itemAName)
            {
                // Delete Item B
                InvCollection collectionA = invInstanceA.GetSource();
                collectionA.Delete(invInstanceA);
    
                // Get the index of Item A
                InvCollection collectionB = invInstanceB.GetSource();
                int indexB = collectionB.IndexOf(invInstanceB);
    
                // Insert Item C
                InvInstance newInvInstance = new InvInstance(newItemName);
                collectionB.Insert(newInvInstance, indexB);
    
                // Delete item A
                collectionB.Delete(invInstanceB);
            }
        }
    
    }
    

    (2) Suppose ItemA has "can carry multiple?" unchecked. There is one copy of ItemA in your inventory, and another copy in the container. If you click on the container copy and take it to the inventory, the inventory (correctly) won't take it. But if you take a different item (ItemD) from the inventory and click on the container copy of ItemA, they will swap places and you will have two copies of ItemA even though you aren't supposed to!

    (3) I see that it's not possible to click on an inventory item (ItemA) and then combine it with a container item (ItemB) before moving ItemA to the container first. Instead of the combine interaction, what happens is that they swap slots (ItemA ends up in the container, and ItemB is moved to the inventory). I agree that this should be the default behaviour, but the hotspot label should not display the usual "Use ItemA on ItemB" message.

    (4) On the other hand, when you select a container item (ItemB) and then click on an inventory item (ItemA), the items are neither combined nor swaped: itemB is simply added to the inventory. I suggest that the items should be swapped so the behaviour is always the same.

    (5) Finally, I see that selecting an item and then clicking on the same slot where it used to be triggers a combine interaction. This makes sense if the item still appears to be there (graphically), but when the selected item's display is set to "hide from menu", I don't think it makes sense for this combine interaction to happen.

  • (1) The code you provided has a bug

    Rather than writing two sets of the same code, try just checking if the two items are the same. I'll update the code at the bottom of this post.

    (4) when you select a container item (ItemB) and then click on an inventory item (ItemA), the items are neither combined nor swaped: itemB is simply added to the inventory. I suggest that the items should be swapped so the behaviour is always the same.

    Swapping occurs when clicking a Container due to a Container's optional maximum capacity. To swap an item in the Inventory, you'd need to script it. To incorporate this into the same script, you'd need to make sure you only have one instance of the script - so as not to have the same code be run multiple times. I've updated the script to rely on an array, so that you can define multiple replacements in one component.

    As for the other issues, I'll look into them.

    using AC;
    using UnityEngine;
    
    public class DynamicReplaceItem : MonoBehaviour
    {
    
        [SerializeField] private ItemSwapData[] itemSwapDatas;
    
        private void OnEnable () { EventManager.OnInventoryCombine_Alt += OnInventoryCombine; }
        private void OnDisable () { EventManager.OnInventoryCombine_Alt -= OnInventoryCombine; }
    
        private void OnInventoryCombine (InvInstance invInstanceA, InvInstance invInstanceB)
        {
            if (invInstanceA == invInstanceB) return;
    
            InvCollection collectionA = invInstanceA.GetSource ();
            InvCollection collectionB = invInstanceB.GetSource ();
            int indexB = collectionB.IndexOf (invInstanceB);
    
            foreach (ItemSwapData itemSwapData in itemSwapDatas)
            {
                // Check if item names match
                if ((invInstanceA.InvItem.label == itemSwapData.itemAName && invInstanceB.InvItem.label == itemSwapData.itemBName) || 
                    (invInstanceB.InvItem.label == itemSwapData.itemAName && invInstanceA.InvItem.label == itemSwapData.itemAName))
                {
                    // Delete Item A
                    collectionA.Delete (invInstanceA);
    
                    // Insert Item C
                    InvInstance newInvInstance = new InvInstance (itemSwapData.newItemName);
                    collectionB.Insert (newInvInstance, indexB);
    
                    // Delete item B
                    collectionB.Delete (invInstanceB);
                    return;
                }
            }
    
            // Swap A and B?
            if (collectionB == KickStarter.runtimeInventory.PlayerInvCollection && collectionA != collectionB)
            {
                KickStarter.runtimeInventory.PlayerInvCollection.Insert (invInstanceA, indexB, OccupiedSlotBehaviour.SwapItems);
            }
        }
    
    
        [System.Serializable]
        private class ItemSwapData
        {
    
            public string itemAName = "ItemA";
            public string itemBName = "ItemB";
            public string newItemName = "ItemC";
    
        }
    
    }
    
  • Thank you! Just to make sure I understood it right – so if I want this behaviour for several sets of items, should I just add new public strings to ItemSwapData, and also add similar if statements under foreach?
  • You can use the Inspector to add as many item swaps as you like. No need to edit the code.

    Regarding your other issues:

    (2) is a bug, and will be addressed.

    (5) is not something I can recreate - can you share your full Settings? Though, the easiest way to prevent self-comining is just to disable the interactions themselves in the Inventory Manager.

    (3) seems a little too specific to your needs, so I feel it's best handled in a custom script as well:

    using UnityEngine;
    using AC;
    ​
    public class CustomContainerHotspot : MonoBehaviour
    {
    ​
        private void OnEnable () { EventManager.OnRequestMenuElementHotspotLabel += OnRequestMenuElementHotspotLabel; }
        private void OnDisable () { EventManager.OnRequestMenuElementHotspotLabel -= OnRequestMenuElementHotspotLabel; }
    ​
        private string OnRequestMenuElementHotspotLabel (Menu _menu, MenuElement _element, int _slot, int _language)
        {
            MenuInventoryBox menuInventoryBox = _element as MenuInventoryBox;
    ​
            if (menuInventoryBox != null && menuInventoryBox.inventoryBoxType == AC_InventoryBoxType.Container)
            {
                if (InvInstance.IsValid (KickStarter.runtimeInventory.SelectedInstance) && KickStarter.runtimeInventory.SelectedInstance.GetSource () == KickStarter.runtimeInventory.PlayerInvCollection)
                {
                    InvInstance containerInstance = menuInventoryBox.GetInstance (_slot);
                    if (InvInstance.IsValid (containerInstance))
                    {
                        return containerInstance.InvItem.GetLabel (_language);
                    }
                }
            }
    ​
            return string.Empty;
        }
    ​
    }
    
  • edited February 2021

    Thank you! I needed the inventory hotspot to get the item label too, not just the container one, but it was super easy to adapt your code to work the other way around.

    I did come across an issue with the DynamicReplaceItem script though. This bit:

            if (collectionB == KickStarter.runtimeInventory.PlayerInvCollection && collectionA != collectionB)
            {
                Debug.Log("swap?");
                KickStarter.runtimeInventory.PlayerInvCollection.Insert(invInstanceA, indexB, OccupiedSlotBehaviour.SwapItems);
            }
        }
    

    The Debug.Log message is never printed to the console. It is only ever printed if I delete the "collectionA != collectionB" condition (in which case it's printed when both items used are in the inventory). If I delete the first condition, "swap?" is never printed either, no matter which direction the items are going. This makes me believe either that the default transfer between both inventories takes precedence over OnInventoryCombine_Alt, or that combines between different inventories don't trigger OnInventoryCombine_Alt at all.

  • edited February 2021

    Oh, and regarding (5), it was just something I noticed when I added a Debug.Log to the very start of the OnInventoryCombine method, before all the if statements. If ItemA is in slot 1, for example, and I pick it up, and then place it back in slot 1, then the method is triggered via OnInventoryCombine_Alt. Does this not happen with you? I thought it was intended so you could use an item on itself, but that doesn't make much sense when to the end user the item is not actually there graphically.

  • This makes me believe either that the default transfer between both inventories takes precedence over OnInventoryCombine_Alt, or that combines between different inventories don't trigger OnInventoryCombine_Alt at all.

    You may be right - I'll take a look.

    If ItemA is in slot 1, for example, and I pick it up, and then place it back in slot 1, then the method is triggered via OnInventoryCombine_Alt. Does this not happen with you?

    Again, it depends on the settings. But I'd say it's best to have an event trigger than not - you can always discount it in the code by checking if the two items in the event's parameters are equal.

  • On the item transfer behaviour: you're correct. The behaviour is built-in, as items can get moved around etc based on your settings automatically.

    To have an item from a Container be swapped when using it on an item in the Player's inventory, you'll have to rely instead on the OnMenuElementClick event:

    using AC;
    using UnityEngine;
    ​
    public class SwapItems : MonoBehaviour
    {
    ​
        private void OnEnable () { EventManager.OnMenuElementClick += OnMenuElementClick; }
        private void OnDisable () { EventManager.OnMenuElementClick -= OnMenuElementClick; }
    ​
        private void OnMenuElementClick (Menu menu, MenuElement element, int slot, int buttonPressed)
        {
            if (menu.title == "Inventory" && element.title == "InventoryBox")
            {
                MenuInventoryBox inventoryBox = element as MenuInventoryBox;
                InvInstance clickedInstance = inventoryBox.GetInstance (slot);
                InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
    ​
                if (InvInstance.IsValid (clickedInstance) && InvInstance.IsValid (selectedInstance))
                {
                    if (selectedInstance.GetSource () != KickStarter.runtimeInventory.PlayerInvCollection)
                    {
                        if (!clickedInstance.InvItem.canCarryMultiple && selectedInstance.GetSource ().Contains (clickedInstance.ItemID))
                        {
                            // Don't allow swapping
                            return;
                        }
                        KickStarter.runtimeInventory.PlayerInvCollection.Insert (KickStarter.runtimeInventory.SelectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                        KickStarter.runtimeInventory.SetNull ();
                    }
                }
            }
        }
    ​
    }
    

    The main issue here is that this will conflict with the said default behaviour. To have this work properly, you'd also need to set the InventoryBox element's Inventory box type field to Custom Script.

    This also means that all other click behaviour would have to be hard-coded, which'd mean extending the script above to handle things like selecting clicked items, etc. Though, this method does give you full control over exactly how the menu behaves.

  • Thanks! I think I can manage to extend the script. I haven't really been able to try though because setting the inventory box type field to Custom Script doesn't seem to be working?

    I included a debug.log right after this line:

        private void OnMenuElementClick (Menu menu, MenuElement element, int slot, int buttonPressed)
        {
    

    And when I click on an inventory menu element set to Custom Script, I don't get any messages on the console. Isn't that what is supposed to happen? I tried two different inventory menus too, just to make sure there wasn't anything wrong with them. I checked my other scripts and none of them deals with OnMenuElementClick, so I don't think there's anything interfering.

    Also, since we are at it, can you point me to where the code for the default inventory box type is? I'm going to replicate most of its behaviour, so it might be easier if I can see how you coded it originally.

  • edited February 2021

    Sorry, I can't edit the post anymore, but I've only now realised I forgot to attach the script to a game object lol.

    All good now, I just need to find the default inventory box code so I can adapt it.

    Edit: never mind, found it. I should be able to cobble something together.

  • OK, Chris, I'm not a coder, but this is working as far as Inventory clicks are concerned. I'm struggling a bit to figure out how to make the exact same click behaviour apply to Container clicks, though. Any pointers? (I only got as far as duplicating the code and changing the menu names).

    using AC;
    using UnityEngine;
    
    public class SwapItems : MonoBehaviour
    {
    
        private void OnEnable() { EventManager.OnMenuElementClick += OnMenuElementClick; }
        private void OnDisable() { EventManager.OnMenuElementClick -= OnMenuElementClick; }
    
        private void OnMenuElementClick(Menu menu, MenuElement element, int slot, int buttonPressed)
        {
    
            if (menu.title == "Inventory Bar" && element.title == "InventoryBox")
            {
                MenuInventoryBox inventoryBox = element as MenuInventoryBox;
                InvInstance clickedInstance = inventoryBox.GetInstance(slot);
                InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
    
    
                // Click on an occupied slot while holding another item
                if (InvInstance.IsValid(clickedInstance) && InvInstance.IsValid(selectedInstance))
                {
                    // Swap items if the selected item came from a container (if multiple can be carried, add to stack in inventory)
                    if (selectedInstance.GetSource() != KickStarter.runtimeInventory.PlayerInvCollection)
                    {
    
                        // Do nothing when items are the same and multiples are not allowed
                        if (!clickedInstance.InvItem.canCarryMultiple && selectedInstance.GetSource().Contains(clickedInstance.ItemID))
                        {
                            KickStarter.runtimeInventory.SetNull();
                            return;
                        }
    
                        KickStarter.runtimeInventory.PlayerInvCollection.Insert(KickStarter.runtimeInventory.SelectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                        KickStarter.runtimeInventory.SetNull();
                        return;
                    }
                    // Combine items if they both come from the inventory
                    else
                    {
                        // Dealing with stackable items
                        if (clickedInstance.InvItem.canCarryMultiple && selectedInstance.GetSource().Contains(clickedInstance.ItemID))
                        {
                            // Merge stacks
                            if (buttonPressed == 1)
                            {
                                KickStarter.runtimeInventory.PlayerInvCollection.Insert(KickStarter.runtimeInventory.SelectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                                KickStarter.runtimeInventory.SetNull();
                                return;
                            }
                            // Take one from stack
                            if (buttonPressed == 2)
                            {
                                KickStarter.runtimeInventory.SelectItem(clickedInstance);
                                return;
                            }
                        }
                        selectedInstance.Combine(clickedInstance, false);
                        return;
                    }
                }
    
                // Place item in free slot
                if ((InvInstance.IsValid(clickedInstance) == false) && InvInstance.IsValid(selectedInstance))
                {
                    KickStarter.runtimeInventory.PlayerInvCollection.Insert(KickStarter.runtimeInventory.SelectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                    KickStarter.runtimeInventory.SetNull();
                    return;
                }
    
                // Click on an item without holding anything
                if (InvInstance.IsValid(clickedInstance) && (InvInstance.IsValid(selectedInstance) == false))
                {
                    // Dealing with stackable items
                    if (clickedInstance.InvItem.canCarryMultiple)
                    {
                        // Take all by left clicking
                        if (buttonPressed == 1)
                        {
                            int count = clickedInstance.Count;
                            while (count > 0)
                            {
                                KickStarter.runtimeInventory.SelectItem(clickedInstance);
                                count--;
                            }                        
                        }
                        // Take one from stack by right clicking
                        if (buttonPressed == 2)
                        {
                            KickStarter.runtimeInventory.SelectItem(clickedInstance);                        
                        }
                        return;
                    }
                    // Take item
                    KickStarter.runtimeInventory.SelectItem(clickedInstance);
                    return;
    
                }
    
    
    
            }
    
    
        }
    }
    
  • As in, completely override the behaviour of clicking a Container element as well?

    You can replace the element title check with a blanket "Is a custom inventory box" check by swapping:

    if (menu.title == "Inventory Bar" && element.title == "InventoryBox")
    {
        MenuInventoryBox inventoryBox = element as MenuInventoryBox;
    

    with:

    MenuInventoryBox inventoryBox = element as MenuInventoryBox;
        if (inventoryBox != null && inventoryBox.inventoryBoxType == AC_InventoryBoxType.CustomScript)
        {
    

    That way, the code will run for all InventoryBox elements set to Custom Script.

    This means, though, that your Container element would also have to be set to Custom Script. The issue with that is that you then have to link the open Container to the Container element manually, but this can also be done through script:

    using UnityEngine;
    using AC;
    
    public class MapContainerToMenu : MonoBehaviour
    {
    
        private void OnEnable () { EventManager.OnMenuTurnOn += OnMenuTurnOn; }
        private void OnDisable () { EventManager.OnMenuTurnOn -= OnMenuTurnOn; }
    
        private void OnMenuTurnOn (AC.Menu _menu, bool isInstant)
        {
            if (_menu.title == "Container")
            {
                MenuInventoryBox containerBox = PlayerMenus.GetElementWithName ("Container", "ContainerBox") as MenuInventoryBox;
                containerBox.OverrideContainer = KickStarter.playerInput.activeContainer;
            }
        }
    
    }
    

    Note that you'd have to manually turn on your Container menu after using the Container: Open Action, since setting its type to Custom Script will prevent it from turning on automatically.

  • The issue I'm having with this solution is that when I open the container, all the container contents are there, but as soon as I click on any inventory menu at all (either the container box that was overridden by the script above to display the active container's content, or the other menu that displays the player inventory next to it), the container menu instantly reverts its contents to the player inventory. This happens even when clicking on empty slots. It also happens when I comment out ALL the contents of my custom OnMenuElementClick method.

    I was reading the description of the OverrideContainer function, and this caught my attention:

    If set, and inventoryBoxType = AC_InventoryBoxType.Container, then this Container will be used instead of the global 'active' one. Note that its Menu's 'Appear type' should not be set to 'On Container'.

    The the inventory box type is no longer Container, it's CustomScript. Might this be the problem?

  • A custom inventory box should still be able to list a Container's items if OverrideContainer is set.

    It may be that we just need a different way to set OverrideContainer.

    Rather than the above script, try instead this one as a test:

    using UnityEngine;
    using AC;
    
    public class MapContainerToMenu : MonoBehaviour
    {
    
        public Container myContainer;
    
        [ContextMenu ("Open container")]
        public void OpenContainer ()
        {
            MenuInventoryBox containerBox = PlayerMenus.GetElementWithName ("Container", "ContainerBox") as MenuInventoryBox;
            containerBox.OverrideContainer = myContainer;
            PlayerMenus.GetMenuWithName ("Container").TurnOn ();
        }
    
    }
    

    Rename the menu/element names, place it in the scene, and assign one of your Containers in its Inspector. At runtime, then go to its cog menu at the top-right and click "Open container". This should then assign the Container to the element, and open the Menu.

    Does the Container then remain mapped to the element?

  • edited February 2021

    Yes, that worked! Thank you. I'm still running into trouble with one little bit of my inventory/container click override script though, if you could try and shed a light on it for me.

    The issue I'm running into is that KickStarter.runtimeInventory.PlayerInvCollection.Insert always inserts the selected item into the player inventory, even when I'm clicking on a container menu slot. I tried fixing this problem by using collectionClicked.Insert instead, which works! But only when clickedInstance is valid, which only returns true when the clicked slot is already occupied. So under the "Place item in free slot" section, I just don't know how to proceed. I don't know how to retrieve the InvCollection attached to an empty menu slot. As a last resort, I tried doing two if statements (one for the inventory menu, and one for the container menu), which got the inventory working again, but I still don't know how to insert an item into the active container's empty slot.

    using AC;
    using UnityEngine;
    
    public class CustomInventories : MonoBehaviour
    {
    
        private void OnEnable() { EventManager.OnMenuElementClick += OnMenuElementClick; }
        private void OnDisable() { EventManager.OnMenuElementClick -= OnMenuElementClick; }
    
        private void OnMenuElementClick(Menu menu, MenuElement element, int slot, int buttonPressed)
        {
    
    
            MenuInventoryBox inventoryBox = element as MenuInventoryBox;
            InvInstance clickedInstance = inventoryBox.GetInstance(slot);
            InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
            InvCollection collectionClicked;
            InvCollection collectionSelected;
    
            if (inventoryBox != null && inventoryBox.inventoryBoxType == AC_InventoryBoxType.CustomScript)
            {
    
    
                // Click on an occupied slot while holding another item
                if (InvInstance.IsValid(clickedInstance) && InvInstance.IsValid(selectedInstance))
                {
                    collectionClicked = clickedInstance.GetSource();
                    collectionSelected = selectedInstance.GetSource();
    
                    // Swap items if the selected item came from a different collection (if multiple can be carried, add to stack)
                    if (collectionClicked != collectionSelected)
                    {
    
                        // Do nothing when items are the same and multiples are not allowed
                        if (!clickedInstance.InvItem.canCarryMultiple && collectionSelected.Contains(clickedInstance.ItemID))
                        {
                            KickStarter.runtimeInventory.SetNull();
                            return;
                        }
    
                        collectionClicked.Insert(selectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                        KickStarter.runtimeInventory.SetNull();
                        return;
                    }
                    // Combine items if they both come from the same collection
                    else
                    {
                        // Dealing with stackable items
                        if (clickedInstance.InvItem.canCarryMultiple && collectionSelected.Contains(clickedInstance.ItemID))
                        {
                            // Merge stacks
                            if (buttonPressed == 1)
                            {
                               collectionClicked.Insert(selectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                               KickStarter.runtimeInventory.SetNull();
                                return;
                            }
                            // Take one from stack
                            if (buttonPressed == 2)
                            {
                                KickStarter.runtimeInventory.SelectItem(clickedInstance);
                                return;
                            }
                        }
                        selectedInstance.Combine(clickedInstance, false);
                        return;
                    }
                }
    
                // Place item in free slot
                if (!InvInstance.IsValid(clickedInstance) && InvInstance.IsValid(selectedInstance))
                {
    
                    //collectionClicked = clickedInstance.GetSource();
    
                    if (menu.title == "Inventory Bar" && element.title == "InventoryBox")
                    {
    
                        KickStarter.runtimeInventory.PlayerInvCollection.Insert(KickStarter.runtimeInventory.SelectedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                        KickStarter.runtimeInventory.SetNull();
                        return;
    
                    }
    
                    if (menu.title == "Container Box" && element.title == "Container")
                    {
    
                        // collectionClicked.Insert(clickedInstance, slot, OccupiedSlotBehaviour.SwapItems);
                        // KickStarter.runtimeInventory.SetNull();
                        return;
    
                    }
    
    
    
                    return;
                }
    
                // Click on an item without holding anything
                if (InvInstance.IsValid(clickedInstance) && !InvInstance.IsValid(selectedInstance))
                {
    
                    // Dealing with stackable items
                    if (clickedInstance.InvItem.canCarryMultiple)
                    {
                        // Take all by left clicking
                        if (buttonPressed == 1)
                        {
                            int count = clickedInstance.Count;
                            while (count > 0)
                            {
                                KickStarter.runtimeInventory.SelectItem(clickedInstance);
                                count--;
                            }                        
                        }
                        // Take one from stack by right clicking
                        if (buttonPressed == 2)
                        {
                            KickStarter.runtimeInventory.SelectItem(clickedInstance);                        
                        }
                        return;
                    }
                    // Take item
                    KickStarter.runtimeInventory.SelectItem(clickedInstance);
                    return;
    
                }
    
    
    
            }
    
    
    
        }
    }
    
  • Since you're hooking into the OnMenuElementClick event, you can extract this from the Container it's mapped to:

    inventoryBox.OverrideContainer.InvCollection
    

    Naturally, this'll only work if the InventoryBox element in question is being manually overridden with a Container - so you'll need to also check the element's title to make sure you only check this if the name matches, i.e.:

    InvCollection collection = (inventoryBox.title == "Container") ? inventoryBox.OverrideContainer.InvCollection : KickStarter.runtimeInventory.PlayerInvCollection;
    
  • edited March 2021

    Thank you! That also works.

    You might have noticed above that I have a couple of lines like this:

    selectedInstance.Combine(clickedInstance, false);

    I thought that if both instances were combined, but I didn't specify any "combine" interactions in the AC Game Editor, it would run the unhandled interaction I specified in the Editor. Is this not supposed to happen?

  • So long as the two instances represent separate items, the unhandled should run.

    Is your unhandled interaction assigned as a per-item property, or for all items at the top?

    You can try placing Debug.Log statements in the InvInstance script's Combine function to see how far through the function it gets - the unhandled interaction is only run if it reaches the bottom.

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.