Forum rules - please read before posting.

Scripting help: Parameter via script, Selected Item From Container.

Hi!
I'm making a "simple" weight & Item slot limited, multiple player inventories. I made all the giving/picking via actionlists logic and all is fine. I'm using temporal global variables when changing player to handle current weight etc, No problem there.

The only final part I need is able to add the weight when picking from a container; It looked like something easy to do as I'm using the script from the wiki LimitItemsFromContainer, and My idea was triggering an actionlist that increase the weight property of the selected item, when the wiki script triggers that the item can be picked; Problem is that I need to set the parameter of what item is being picked. I've been reading about running actionlists with parameters but I'm not been lucky implementing it into the code.

PS: I don't care about going over weigh limit, I'll just make that you cannot close the container if you are over the weight limit, so I only need to trigger the Weight Add from the Current added item, no more math checking involved.

I'm not sure what I'm doing wrong; This is what I added when an item is added via that script:

 ActionListAsset AddWeighActionList = Resources.Load("ActionLists/ContainerAddWeight", typeof(ActionListAsset)) as ActionListAsset;

AddWeighActionList.parameters[0].SetValue(selectedInstance);

AddWeighActionList.Interact();

Is there something wrong?

This would be the full script:

using UnityEngine;

using AC;

public class LimitItemsFromContainerLittle : MonoBehaviour

{

    public int maxItems = 8;
  // public ActionListAsset AddWeighActionList;

    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 == "ContainerLittle" && element.title == "PlayerInventory")

        {

            MenuInventoryBox inventoryBox = element as MenuInventoryBox;

            InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;

            if (InvInstance.IsValid(selectedInstance))

            {

                int numItems = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();

                if (numItems < maxItems)

                {

                    KickStarter.runtimeInventory.Add(selectedInstance);

                    //
                    ActionListAsset AddWeighActionList = Resources.Load("ActionLists/ContainerAddWeight", typeof(ActionListAsset)) as ActionListAsset;


                    AddWeighActionList.parameters[0].SetValue(selectedInstance);

                    AddWeighActionList.Interact();

                    //
                }

            }

            else

            {

                InvInstance clickedInstance = inventoryBox.GetInstance(slot);

                if (InvInstance.IsValid(clickedInstance))

                {

                    clickedInstance.Select();

                }

            }

        }

    }

}

So, a pair of problems here:

-"Actionlist parameters is not accessible because its protection level"
-"Can't convert AC.InvInstance to Int"

So, is there a way that I can make this work?

There is of course another way to solve this easily on my setup that doesn't involve triggering an Actionlist with parameters, that would be download the weight property from the selected item and updating the temporal global variable... but that's another code that I'll need to investigate.

I'm also not sure if I'm using the Resources folder correctly, 'cause I don't usually work with the resources folder from scripting, but I guess I'm doing it right from common sense.

Comments

  • Actionlist parameters is not accessible because its protection level

    You need to get the parameter using the GetParameter function:

    ActionParameter myParameter = AddWeighActionList.GetParameter ("MyParameter");
    

    Can't convert AC.InvInstance to Int

    You're attempting to pass the instance of an Inventory item to a parameter of type Integer.

    You're looking to set this to the value of the item's weight, correct? Is this a property defined in the Inventory Manager?

    You can extract an item's property value from its instance. If it's an Integer property named "Weight", for example:

    int weight = selectedInstance.GetProperty ("Weight").IntegerValue;
    

    Which can then be passed to the parameter:

    myParameter.SetValue (weight);
    
  • Perfect! I made it work flawlessly with this code:

     {
    
                        int weight = selectedInstance.GetProperty("Weight").IntegerValue;
                        KickStarter.runtimeInventory.Add(selectedInstance);
    
    
                        ActionListAsset AddWeighActionList = Resources.Load("ActionLists/ContainerAddWeight", typeof(ActionListAsset)) as ActionListAsset;
                        ActionParameter myParameter = AddWeighActionList.GetParameter(0);
    
                        myParameter.SetValue(weight);
                        AddWeighActionList.Interact();
    
                        //
                    }
    

    But of course I hitted a wall; I forget that I also need to remove the weight when getting back the item from the inventory to the container. (Same, with an Actionlist, Container don't care about weight, I only need to remove the weight from the temporal global variable).

    It is no easy copy-paste work because the Container is another type of element (one very specific), so I can't use the custom script on the element container box makes him forget that is a container, without highly modifying the script in a way I have no clue.

    I've been taking a look at Container scripts on the forums...

    Where do I should start?

    With a OnMenuElementClick (for the Container menu), or with a OnContainerAdd?

    Looks like I can't use the `EventManager.OnContainerAdd += My_OnContainerAdd;

    Basically I need to run

       int weight = selectedInstance.GetProperty("Weight").IntegerValue;
                    ActionListAsset RemoveWeighActionList = Resources.Load("ActionLists/ContainerRemoveWeight", typeof(ActionListAsset)) as ActionListAsset;
                    ActionParameter myParameter = RemoveWeighActionList.GetParameter(0);
    
                    myParameter.SetValue(weight);
                    RemoveWeighActionList.Interact();
    

    So It would make sense that that runs when On Container Add... if that allows me to check the selectedItem that is Add....

    I don't need to use any specific container menu, this behavior will work for all Containers.

  • You can use OnMenuElementClick, and examine the clicked menu/element titles to determine if it's the Container, i.e.:

    private void OnMenuElementClick (AC.Menu menu, MenuElement element, int slot, int buttonPressed)
    {
        if (menu.title == "MyContainerMenu" && element.title == "MyContainerElement")
        {
            MenuInventoryBox containerElement = (MenuInventoryBox) element;
            Container container = containerElement.OverrideContainer != null ? containerElement.OverrideContainer : KickStarter.playerInput.activeContainer;
            // Container 'container' was updated
        }
    }
    
  • I implemented that but, apart from other problems. I think this workflow isn't well suited.

    Not about using Actionlists, but with the method Select and Drag items between container and playerinventory. I guess that worked well for using the CountItems as an internal AC method, but not for what I'm doing or the way I'm doing it.

    I discarded the using of Actionlist and Made some scripts to automate the process and link them to the variables in the future. In order to make a better script... I started to make an actual script.

    Basically the problem is, (Both when using action lists and with the better script):
    1) When just selecting or dragging an item in the playerinventory (In the menu with the container open), the weigh is added, and that is not an intended behaviour. (it registers the click so the adding weight is run)
    2)And in the container part, well, I tried, but I guess I don't know at all how to code that; just when clicking on an item in the container, the weight is reduced.

    So basically I totally need to change how the workflow goes (not dragging but directly interchanging between inventory and container I guess).

    **
    A question: **
    Do I need to have two scripts, one for looking at events registered on the "playerinventory" element, and the other one, for looking at the container element?
    If I try to have only one script with the two, looks like only register events in the first menu element query.

    In the end, I'm going to copy the scripts here (well, the container one works but I don't think I can make it alone.

    using UnityEngine;
    
    using AC;
    
    public class LimitItemsAndWeightFromContainer : MonoBehaviour
    
    {
    
        public int maxItems = 8;
        public int maxWeight = 20;   //To Replace for GVar
        public int currentWeight = 0; //To Replace for GVar
        private int AddedWeight = 0;
    
    
        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 == "Container"  && element.title == "PlayerInventory")
            if ((menu.title == "ContainerLittle" || menu.title == "ContainerBig" || menu.title == "ContainerMedium") && element.title == "PlayerInventory")
    
    
            {
    
                MenuInventoryBox inventoryBox = element as MenuInventoryBox;
    
                InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
    
                if (InvInstance.IsValid(selectedInstance))
    
                {
    
                    int numItems = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
    
                    if (numItems < maxItems)
    
                    {
    
                        int weight = selectedInstance.GetProperty("Weight").IntegerValue;
    
                        AddedWeight = weight + currentWeight;
    
                        if (AddedWeight <= maxWeight)
    
                        {
    
                            KickStarter.runtimeInventory.Add(selectedInstance);
                            currentWeight = currentWeight + weight;
                            AddedWeight = 0;
    
                            Debug.Log("Item And Weight Added");
    
                        }
    
    
                    }
    
    
                }
                else
    
                {
    
                    InvInstance clickedInstance = inventoryBox.GetInstance(slot);
    
                    if (InvInstance.IsValid(clickedInstance))
    
                    {
                        Debug.Log("Just clicked");
    
                        clickedInstance.Select();
    
                    }
    
                }
    
    
    
    
            }
        }
    }
    

    And the Container one... it registers the container menu and reduce weigh when clicking on it (not intended), But not even when dropping an item at it (not intended again). So is just a mess.

    using UnityEngine;
    
    using AC;
    
    public class ReduceWeightOnContainer : MonoBehaviour
    
    {
    
    
        public int currentWeight = 0; //To Replace for GVar
    
        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 == "ContainerLittle" && element.title == "Container")
            if ((menu.title == "ContainerLittle" || menu.title == "ContainerBig" || menu.title == "ContainerMedium") && element.title == "Container")
    
            {
                MenuInventoryBox containerElement = (MenuInventoryBox)element;
                Container container = containerElement.OverrideContainer != null ? containerElement.OverrideContainer : KickStarter.playerInput.activeContainer;
                // Container 'container' was updated
    
    
                InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
    
    
                if (InvInstance.IsValid(selectedInstance))
    
                {
    
    
                    // KickStarter.runtimeInventory.Add(selectedInstance);
    
                    Debug.Log("Container Clicked");
    
                    int weight = selectedInstance.GetProperty("Weight").IntegerValue;
    
    
    
                   // KickStarter.runtimeInventory.Remove(selectedInstance);
                    currentWeight = currentWeight - weight;
    
                    //
    
    
                }
    
                else
    
                {
    
    
                    //   InvInstance clickedInstance = inventoryBox.GetInstance(slot);
                    InvInstance clickedInstance = containerElement.GetInstance(slot);
    
                    if (InvInstance.IsValid(clickedInstance))
    
                      {
    
                            clickedInstance.Select();
    
                      }
    
                }
    
            }
    
    
        }
    
    }
    

    I guess that if this code can be easily changed to execute the events when the item is transfered, it will be feasible, but it don't look feasible when draging and droping and the inventory elements not recognising if they're getting a new item.

    So, All help is welcome, but if is too much help to ask I'll just remove all weight code from the project and... I don't know. Just code different player inventory sizes for different characters... I can live without the weight I guess.

    (Btw, It would be nice to have an automatic Actionlist slot for when an item movement is done between inventories... Just the same there is an actionlist entry for when clicking the save button).

  • Both can be combined into one script:

    using UnityEngine;
    using AC;
    
    public class LimitItemsAndWeightFromContainer : MonoBehaviour
    {
    
        public int maxItems = 8;
        public int maxWeight = 20;   //To Replace for GVar
        public int currentWeight = 0; //To Replace for GVar
        private int AddedWeight = 0;
    
        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.StartsWith ("Container"))
            {
                if (element.title == "PlayerInventory")
                {
                    MenuInventoryBox inventoryBox = element as MenuInventoryBox;
                    InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
    
                    if (InvInstance.IsValid(selectedInstance))
                    {
                        int numItems = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
                        if (numItems < maxItems)
                        {
                            int weight = selectedInstance.GetProperty("Weight").IntegerValue;
                            AddedWeight = weight + currentWeight;
                            if (AddedWeight <= maxWeight)
                            {
                                KickStarter.runtimeInventory.Add(selectedInstance);
                                currentWeight = currentWeight + weight;
                                AddedWeight = 0;
    
                                Debug.Log("Item And Weight Added");
                            }
                        }
                    }
                    else
                    {
                        InvInstance clickedInstance = inventoryBox.GetInstance(slot);
                        if (InvInstance.IsValid(clickedInstance))
                        {
                            Debug.Log("Just clicked");
                            clickedInstance.Select();
                        }
                    }
                }
                else if (element.title == "Container")
                {
                    MenuInventoryBox containerElement = (MenuInventoryBox)element;
                    Container container = containerElement.OverrideContainer != null ? containerElement.OverrideContainer : KickStarter.playerInput.activeContainer;
                    // Container 'container' was updated
    
                    InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
                    if (InvInstance.IsValid(selectedInstance))
                    {
                        // KickStarter.runtimeInventory.Add(selectedInstance);
                        Debug.Log("Container Clicked");
                        int weight = selectedInstance.GetProperty("Weight").IntegerValue;
                        // KickStarter.runtimeInventory.Remove(selectedInstance);
                        currentWeight = currentWeight - weight;
                        //
                    }
                    else
                    {
                        // InvInstance clickedInstance = inventoryBox.GetInstance(slot);
                        InvInstance clickedInstance = containerElement.GetInstance(slot);
                        if (InvInstance.IsValid(clickedInstance))
                        {
                            clickedInstance.Select();
                        }
                    }
                }
            }
        }
    
    }
    

    When it comes to calculating the total weight, though, it's probably best to just have a function that just looks at all items in the inventory from scratch - rather than adding/subtracting the last item to be added/removed. That way, it'll always be correct even if it's run at the wrong time.

    AC has a function, GetTotalIntProperty, that returns the total amount of an integer property found in an inventory collection. The total amount of your weight property can be gotten with:

    KickStarter.runtimeInventory.PlayerInvCollection.GetTotalIntProperty (weightPropertyID);
    

    Where "weightPropertyID" is the ID number of the weight property.

  • That function is godsend. After these years I should start checking more the Scripting guide instead of the manual....

    I'm very glad I'm trying to make this script. I have a problem tho. I've updated the script to work with the global variables, and Been trying for four hours but...

    Trying to retrieve the int of TotalIntProperty... function
    KickStarter.runtimeInventory.PlayerInvCollection.GetTotalIntProperty returns null, like if there were no propierties, or there were no playerinventorycollection to check the property specifically, because I made a test with "selectedInstance.GetProperty(0)" as a public invvar and gets the results fine; Property is fine with data contained.

    But with the function that you provide me, returns
    NullReferenceException: Object reference not set to an instance of an object
    AC.InvCollection.GetTotalIntProperty (System.Int32 propertyID) (at Assets/AdventureCreator/Scripts/Inventory/InvCollection.cs:941)

    there is some problem somewhere and I can't find where.

    When this is solved, looks like everything will work as a charm.

    using UnityEngine;
    using System.Collections.Generic;
    using AC;
    
    
    public class LimitItemsAndWeightFromContainer : MonoBehaviour
    {
    
        public int maxItems = 8;
    
        private int currentWeight = 0; //Temporal Int to make calculations
        private int AddedWeight = 0;
    
        //DEBUG STUFF
        public InvVar testgetproperty;
    
        //
    
    
        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.StartsWith("Container"))
            {
                if (element.title == "PlayerInventory")
                {
                    MenuInventoryBox inventoryBox = element as MenuInventoryBox;
                    InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
    
                    if (InvInstance.IsValid(selectedInstance))
                    {
    
                        //Were going to calculate number of items at the same time we stored that data for when players change for other uses
                        GVar numberofitemsGVAR = AC.GlobalVariables.GetVariable(18);
                        numberofitemsGVAR.IntegerValue = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
    
                        if (numberofitemsGVAR.IntegerValue < maxItems)
                        {
                            int weight = selectedInstance.GetProperty("Weight").IntegerValue;
    
                            //Get Current Weight Var and Add current selected item weight for calculating if allowed
                            GVar currentWeightGVAR = AC.GlobalVariables.GetVariable(17);
                            currentWeight = currentWeightGVAR.IntegerValue;
                            AddedWeight = weight + currentWeight;
    
                            //Get Max Weight form each character from Gvar
                            GVar maxWeightGVAR = AC.GlobalVariables.GetVariable(16);
    
    
                            if (AddedWeight <= maxWeightGVAR.IntegerValue)
                            {
                                KickStarter.runtimeInventory.Add(selectedInstance);
                                currentWeight = currentWeight + weight;
    
                                //DEBUG stuff
                                testgetproperty =  selectedInstance.GetProperty(0);
                                Debug.Log("Item And Weight Added");
                                //
    
    
                                //Temporal Update Current Weight - this should be unnecesary after we get all the Weight Check
                                // currentWeightGVAR.IntegerValue = AddedWeight;
    
                                //We Update Number of Items
                                numberofitemsGVAR.IntegerValue = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
    
    
                                //Update All Weight, THIS RETURNS NULL
                                currentWeightGVAR.IntegerValue = KickStarter.runtimeInventory.PlayerInvCollection.GetTotalIntProperty (0);
    
    
    
    
    
    
                            }
                        }
                    }
                    else
                    {
                        InvInstance clickedInstance = inventoryBox.GetInstance(slot);
                        if (InvInstance.IsValid(clickedInstance))
                        {
                            Debug.Log("Just clicked");
                            // UPDATE TOTAL WEIGHT HERE AGAIN JUST TO BE SURE
                            // UPDATE NUMBER OF ITEMS CARRIED AGAIN
                            GVar numberofitemsGVAR = AC.GlobalVariables.GetVariable(18);
                            numberofitemsGVAR.IntegerValue = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
                            clickedInstance.Select();
                        }
                    }
                }
                else if (element.title == "Container")
                {
                    MenuInventoryBox containerElement = (MenuInventoryBox)element;
                    Container container = containerElement.OverrideContainer != null ? containerElement.OverrideContainer : KickStarter.playerInput.activeContainer;
                    // Container 'container' was updated
    
                    InvInstance selectedInstance = KickStarter.runtimeInventory.SelectedInstance;
                    if (InvInstance.IsValid(selectedInstance))
                    {
    
                        Debug.Log("Container Clicked 1 ");
    
                        //  UPDATE TOTAL WEIGHT HERE AGAIN JUST TO BE SURE
                        // // UPDATE NUMBER OF ITEMS CARRIED AGAIN
                        GVar numberofitemsGVAR = AC.GlobalVariables.GetVariable(18);
                        numberofitemsGVAR.IntegerValue = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
                    }
                    else
                    {
    
                        InvInstance clickedInstance = containerElement.GetInstance(slot);
                        if (InvInstance.IsValid(clickedInstance))
                        {
                            clickedInstance.Select();
                            Debug.Log("Container Clicked 2 ");
                            //  UPDATE TOTAL WEIGHT HERE AGAIN JUST TO BE SURE
                            // UPDATE NUMBER OF ITEMS CARRIED AGAIN
                            GVar numberofitemsGVAR = AC.GlobalVariables.GetVariable(18);
                            numberofitemsGVAR.IntegerValue = KickStarter.runtimeInventory.PlayerInvCollection.GetCount();
                        }
                    }
                }
            }
        }
    
    }
    
  • I also tried using...

    int WeightPropertyID = selectedInstance.GetProperty("Weight").id;

    to get the property to assign in that function (and yes, is the property with id 0... I don't know. I don't know what don't work.

  • Looks like a bug on the AC side of things.

    Open up AC's InvCollection script and look for the GetTotalIntProperty function (around line 935). Replace it with the following:

    public int GetTotalIntProperty (int propertyID)
    {
        int result = 0;
        foreach (InvInstance invInstance in invInstances)
        {
            if (!InvInstance.IsValid (invInstance)) continue;
            InvVar invVar = invInstance.GetProperty (propertyID);
            if (invVar != null && invVar.type == VariableType.Integer)
            {
                result += invVar.IntegerValue;
            }
        }
        return result;
    }
    

    Does that fix it?

  • It totally fixed it! I feel less useless with coding now XD
    Now works perfect.

    Yesterday I tried with the GetTotalFloatProperty too (Also I probably change the weigh system to use float), so I guess it has the same bug in the code!

  • Indeed - but with this feedback I'll be able to go in and make the necessary changes to the official release. Thanks for the report.

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.