Forum rules - please read before posting.

Need help with writing a custom event for inventory/container.

Hi, I've tried doing this on my own but I just can't wrap my head around it... so I'll need help. Please ;)

Using AC v.1.68.4 - UNITY 2019.2.0f1

In my new game I'm using inventory with limited number of slots (30) and containers (10 slots) to take new items from/store items (it's not a typical point & click). The game is direct controlled with cursor controls in menus only.

Inventory menu looks like this:

https://imgur.com/mThkUkD

Container menu:

https://imgur.com/riQ4o8H

I've managed to use properties to create my own ActionList for taking items which takes care for counting max items and doesn't allow player to take more than 30. Here's what that looks like:

https://imgur.com/0VMXdpw

As you see, I have 2 global variables that control inventory - currentInventory and maxInventory. And that works fine whenever I want to add/remove items through action lists in scripted scenes (I'd use my own ActionList then instead of AC's Inventory-> Add/Remove item). But when it comes to using containers it won't add/remove value to my variables or check what they are, obviously. I read up and clearly what I need is to use CustomEvent for whenever player adds item to container or from container to inventory, because I want to add to the existing AC code to expand it a bit to my needs. But here's where I get stumped... cos it's all so freaking complicated! ;) (and I already have one big commercial title under my belt made with AC and 3 in AGS so I wouldn't say I'm a noob :P ok, maybe coding noob)

I managed to replicate this (to learn): https://adventurecreator.org/tutorials/calling-custom-events

But while I think I understand the logic behind this, I can't find the right commands for what I want to achieve... Like if I knew what to say but couldn't find the right words... The "dictionary" ( https://adventurecreator.org/scripting-guide/class_a_c_1_1_event_manager.html) confuses the hell out of me too... ;)

I'm not asking for a proverbial fish - I really need a fishing rod here, cos I wanna learn how to do it. I think it's fantastic that you can add to AC so easily (well... ;) ) instead of changing it.

Can someone please help me understand and get this to work?

Thanks ;)

-Rem

Comments

  • I've managed to use properties to create my own ActionList for taking items which takes care for counting max items and doesn't allow player to take more than 30. Here's what that looks like:

    As in, prevent them from holding 30 items in total? The Inventory: Check Action can be used to query the number of items being held by the Player.

    On the topic of events, though, you can make desired variable changes upon changing a Container's contents via the OnContainerAdd and OnContainerRemove events. See the Manual's "Inventory scripting" chapter for a list of these events and more.

    As seen in the scripting guide entries, both of these events make use of Delegate_Container, which has two parameters: Container and ContainerItem. Therefore, any custom event that hooks into them also needs these parameters.

    For example:

    private void OnEnable ()
    {
        EventManager.OnContainerRemove += My_OnContainerRemove;
    }
    
    private void OnDisable ()
    {
        EventManager.OnContainerRemove -= My_OnContainerRemove;
    }
    
    private void My_OnContainerRemove (Container container, ContainerItem containerItem)
    {}
    

    The ContainerItem class stores information about what item was added, and how many.

    The total number of items carried by the player can be read with:

    KickStarter.runtimeInventory.localItems.Count;
    

    (Again, see the Manual's "Inventory scripting" chapter for more on this).

    So, combined with the data stored in ContainerItem, you can check if this value exceeds your limit - and add the item back to the Container.

    private void My_OnContainerRemove (Container container, ContainerItem containerItem)
    {
        if (KickStarter.runtimeInventory.localItems.Count > 30)
        {
            container.Add (containerItem.linkedID, containerItem.count);
            KickStarter.runtimeInventory.localItems.Remove (containerItem.linkedID);
        }
    }
    

    One problem, though: this event is actually called before the item itself is transferred, meaning the script above attempts to remove the item from the Player's inventory before it's actually been added. However, I will look into amending this such that it gets called after, as it's likely best suited to that situation.

  • This is probably a really dumb question... but how do I declare Container and ContainerItem? Sorry, this is a bit hard for me but I'm really trying to understand. I know I asked for the rod, not the fish, but I think I need a little bit more.

    Got this so far (managed to increase currentInventory int when items taken from containers):

    https://imgur.com/pAs6iRt

    But I'm stumped again.

  • Both the Container and ContainerItem are already available in the function, since it passes them as parameters. You don't need to assign container from "GetActiveContainer" - it's already set for you.

  • Well, I've got this so far and I get this error: Assets\BurnhouseLane83\Scripts\InvMaxRem.cs(40,58): error CS1503: Argument 1: cannot convert from 'int' to 'AC.InvItem'

    What am I doing wrong?

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using AC;
    
    
    public class InvMaxRem : MonoBehaviour
    
    {
    
        int currentInventory;
    
    
        // Use this for initialization
        void Update()
        {
    
           int currentInventory = AC.GlobalVariables.GetIntegerValue(12);
    
    
        }
    
        private void My_OnContainerRemove(Container container, ContainerItem containerItem)
        {
    
    
    
             AC.GlobalVariables.SetIntegerValue (12, currentInventory = currentInventory+1);
    
    
    
            if (KickStarter.runtimeInventory.localItems.Count > 30)
            {
    
                Debug.Log("maxInventory");
    
    
    
             container.Add (containerItem.linkedID, containerItem.count);
             KickStarter.runtimeInventory.localItems.Remove (containerItem.linkedID);   ///this line gives error
    
            }
    
    
        }
    
    
        private void OnEnable()
        {
            EventManager.OnContainerRemove += My_OnContainerRemove;
        }
    
        private void OnDisable()
        {
            EventManager.OnContainerRemove -= My_OnContainerRemove;
        }
    
    
    
    
    
    }
    
  • RemRem
    edited October 2019

    Managed to do it by declaring problematic int as myItem:

        public void My_OnContainerRemove(Container container, ContainerItem containerItem)
        {
    
       AC.GlobalVariables.SetIntegerValue(12,  AC.GlobalVariables.GetIntegerValue(12) + 1);
    
        AC.InvItem myItem = AC.KickStarter.runtimeInventory.SelectedItem;
    
            if (KickStarter.runtimeInventory.localItems.Count > 30)
            {
    
                Debug.Log("maxInventory");
    
    
    
                container.Add(containerItem.linkedID, containerItem.count);
                 KickStarter.runtimeInventory.localItems.Remove (myItem);  
                AC.GlobalVariables.SetIntegerValue(12, AC.GlobalVariables.GetIntegerValue(12) - 1);
    
            }
    
        }
    

    The problem now is that I have to do it in reverse, so I've added another function: OnContainerAdd so I could manipilate my currentInventory variable through there but... I can't figure out how to check container's count. I basically need this:

    if (KickStarter.runtimeInventory.localItems.Count > 30)

    but for currently opened container.

    Here's what I got so far for that function:

                public void My_OnContainerAdd(Container container, ContainerItem containerItem)
                {
    
    
    
                    AC.GlobalVariables.SetIntegerValue(12, AC.GlobalVariables.GetIntegerValue(12) - 1);
    
                    AC.InvItem myItem = AC.KickStarter.runtimeInventory.SelectedItem;
    
                    if (??????????????????????????) > 10)
                    { 
                        Debug.Log("maxContainer");
    
    
    
                        container.Remove(containerItem.linkedID, containerItem.count);
                        KickStarter.runtimeInventory.localItems.Add(myItem);   ///this line gives error
                        AC.GlobalVariables.SetIntegerValue(12, AC.GlobalVariables.GetIntegerValue(12) + 1);
    
                    }
    
                }
    

    Also, it seems that every item sent back to the container if inventory is full stacks, whereas I have "can carry multiple" and "place in seperate slots" checked and that's how I want my inventory to go. How do I change it in that code?

  • My mistake with the first. Replace:

    KickStarter.runtimeInventory.localItems.Remove (containerItem.linkedID);
    

    with:

    KickStarter.runtimeInventory.Remove (containerItem.linkedID);
    

    As for the opposite direction, you don't need to get the selected item. Again, it's included in the event's parameters. Replace:

    KickStarter.runtimeInventory.localItems.Add (myItem);
    

    with:

    KickStarter.runtimeInventory.Add (containerItem.linkedID);
    

    To get the number of items in a container:

    container.items.Count
    

    Also, it seems that every item sent back to the container if inventory is full stacks, whereas I have "can carry multiple" and "place in seperate slots" checked and that's how I want my inventory to go. How do I change it in that code?

    The Place in separate slots? option is only used by Inventory menus, not Containers. I shall look into enabling this, however.

  • RemRem
    edited October 2019

    Yes, this is working, all right! Thanks, Chris! I think I tried all sorts of spellings (container.GetCount, container.Count etc) except for the one you've now provided me with now ;)

    BTW, I noticed you updated AC yesterday with a fix for this:

    "this event is actually called before the item itself is transferred, meaning the script above attempts to remove the item from the Player's inventory before it's actually been added. However, I will look into amending this such that it gets called after, as it's likely best suited to that situation."

    So I've applied the update to my AC (just the scripts) to get that working correctly.

    And yes - stacking seems to be the only remaining issue here for now. I've noticed it stacks when it returns an item back to container if inventory is full or when you select an item from inventory and click it on the same type of item in container instead of an empty slot. I would be eternally grateful if you could help me with this one, too ;)

  • Weird unwanted behaviour there! If the inventory is maxed out (30) and you click on the item in a container it does nothing, but if you click again it disappears forever giving this console error:

    https://imgur.com/P57s3gB

    And here's a quick video of this occuring (double clicking on container items):

    https://drive.google.com/open?id=15m8GHkjY1W_ZGE8n5hIGQ0_A-P2kbZf0

  • I'm afraid a script error message is meaningless without context - post the actual script you're using to https://paste.ofcode.org/

  • The error message reports an issue with line 33, but there is nothing there in the script you've posted. What is on line 33 inside your text editor?

    Using the script on my end shows no such issue, though I did need to de-select the inventory item if the inventory maxes out. Try this:

    using UnityEngine;
    using AC;
    
    public class InvMaxRem : MonoBehaviour
    {
    
        private void OnEnable()
        {
            EventManager.OnContainerRemove += My_OnContainerRemove;
            EventManager.OnContainerAdd += My_OnContainerAdd;
    
        }
    
        private void OnDisable()
        {
            EventManager.OnContainerRemove -= My_OnContainerRemove;
            EventManager.OnContainerAdd -= My_OnContainerAdd;
        }
    
        public void My_OnContainerRemove(Container container, ContainerItem containerItem)   /////// on REMOVE
        {
            if (KickStarter.runtimeInventory.localItems.Count > 30)
            {
                Debug.Log("maxInventory");
    
                container.Add(containerItem.linkedID, containerItem.count);
                KickStarter.runtimeInventory.Remove (containerItem.linkedID);
                KickStarter.runtimeInventory.SetNull ();
            }
        }
    
    
        public void My_OnContainerAdd(Container container, ContainerItem containerItem)  /////////// on ADD
        {
            if (container.items.Count > 10)
            {
                Debug.Log("maxContainer");
    
                container.Remove(containerItem.linkedID, containerItem.count);
                KickStarter.runtimeInventory.Add(containerItem.linkedID);
            }
        }
    
    }
    

    I've removed the variable calls as well, but you can add them back in if necessary.

  • With my AC updated (thanks so much for the container not stacking update!), your code in place (I've slapped the script on GameEngine scene object) everything seems to work, except... there's this very weird bug. I made a short video to demonstrate it.

    This is exactly the same code you posted except I changed values: max inventory is 10 and max container is 5. In the video, notice the player has 8 items in inventory and 4 in container and after some fiddling between inventory and container we end up with only 11 items overall instead of 12 total (1 gets lost somewhere... but where does it go? lol ;) )

    Here's that vid:

    https://drive.google.com/open?id=1optQ3TMgEMCBd7qTA4RLkKwpE6MokUEy

  • I shall attempt a recreation. Please share screenshots of your Settings Manager, and the properties of the inventory item shown in the video.

  • Thanks, Chris. I really appreciate it ;)

    SettingsManager: https://imgur.com/KX9dlrv

    Item properties: https://imgur.com/yEC5FMp

    I also wonder why items from the container get instantly teleported to inventory while inventory items they get selected as cursor and you have to manually place them in container (which I would prefer to work both ways like that).

  • The issue is mainly due to the fact that all items in the example are the same. Along with the feature requests, I'll need some time to go through them and address properly.

    PM me in a week or so and I'll send you a package to test.

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.