GML Flexible Inventory System

Discussion in 'Tutorials' started by Cloaked Games, Sep 23, 2017.

  1. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    That is exactly right. Good luck! Just loop through your recipe grid and check if it matches each item. Not too hard if you're familiar with grids and loops.
     
    Nabil Kabour likes this.
  2. Nabil Kabour

    Nabil Kabour Member

    Joined:
    Aug 6, 2018
    Posts:
    67
    I know this is outside the scope of this tutorial. You said that you do not claim this to be the most memory efficient method of having an inventory. Out of interest I wanted to ask what would be a memory efficient method of having an inventory, but I just did a quick test and found that 100,000 items in the item index only uses 30 mb of memory. Still, I find it rather unappealing to have the item index and crafting recipes always in memory. Practically this won't have any adverse effects as shown by the test, but just for curiosity's sake. I understand if you would rather not comment on this. Thanks.
     
    Cloaked Games likes this.
  3. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    The statement about not being the most efficient memory solution was only to clarify that I did not take particular time optimizing the system. I prioritized ease of use and simplicity in concept over anything else. For all I know, it IS the most memory efficient.

    I don't actually know of a more memory efficient method, at least, not one that has the same features and ease of use as this solution. Maybe you could delete and reinitialize the item index in between moments of using it, but to be honest, it's not really worth the effort and might cause unwanted side effects. If your tests don't show any adverse effects for your game (and my uses of the same system in my own games prove functional as well), the don't worry about it. Premature optimization is something to avoid.
     
    Nabil Kabour likes this.
  4. Nabil Kabour

    Nabil Kabour Member

    Joined:
    Aug 6, 2018
    Posts:
    67
    I'm trying to make an inventory system with upgradable items and crafting. I currently have upgradable items by storing all of the items properties (including item_id) in one of the rows of the item index grid, and when adding an item to the inventory I copy the entire item_stat column. I can then upgrade items by modifying the values of item_stat of the inventory. I want the item index to contain the base stats of each item (stats when it is purchased from the shop), and the maximum stats it can be upgraded to have. The best way I can think of is to have a 3d ds_grid, with the first element being the item_id, second stat_type (base or max), and third item_stat. Obviously 3d grids don't exist so I need to use another method. A point to make is I think that hat having the item_id as a grid element while having the item_id stored in the stats is redundant, but I cant think of another way to get the item_stats out of the grid based on the item_id. What do you think?

    Edit: I just realized I could have 2 grids, one for base and one for max stats. Doesn't feel like a good approach though.
     
    Last edited: Oct 9, 2018
    Cloaked Games likes this.
  5. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    Instead, just have two stats. Like, stat.armor, and stat.armor_max. When you copy from the item index you should probably only copy the base stats, and use the item index to look up the map stats when you need them. (They'll already be the same for each instance of the item, so you don't need that part stores individually).

    You can do that by making all of the max stat data stored at the end of the grid, and you copy the left half only.

    But also, two grids is probably a pretty good approach. Maybe better than I just described. It takes the same amount of memory and it's easier to manage. The other thing I'd consider is making the range of variation in modified items mathematically related. For example: say the maximum damage is always 25% more than the base damage. This can let you store less information, and gives you a way to mathematically compare how powerful certain items are. But that may not serve your purpose.
     
    Last edited: Oct 9, 2018
    Nabil Kabour likes this.
  6. Nabil Kabour

    Nabil Kabour Member

    Joined:
    Aug 6, 2018
    Posts:
    67
    Yeah having a relation between base and max stats seems the most reasonable. Saves the hassle of defining every max stat for each item.
     
    Cloaked Games likes this.
  7. Nabil Kabour

    Nabil Kabour Member

    Joined:
    Aug 6, 2018
    Posts:
    67
    I am unsure about the current inventory system though. Like I said I am copying the entire item_stat column into the inventory. It seems rather redundant since some stats are not modified. I would say my item_index rows should be called item_info instead of item_stat. It is currently very easy to work with in the current setup, but it is possible to accidentally change the value of a stat that shouldn't be modified.
     
    Cloaked Games likes this.
  8. Nabil Kabour

    Nabil Kabour Member

    Joined:
    Aug 6, 2018
    Posts:
    67
    And also, for crafting not only do you need to store the ingredients, but also the output item, correct?
     
    Cloaked Games likes this.
  9. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    If you can think of a way that works better for your system, by all means do that. The tutorial is not meant to force you to do it a particular way, just give you a good idea (also it's not meant for modifyable items, though many principles still carry through). I don't think that accidentally modifying the value of a stat you don't want to change should be all that easy to do. You'd have to have a logic error that you caused yourself which would cause problems no matter if those extra values where there or not. Of course, another system would be to do something and store only the values that are pertinent for a particular item, like Minecraft which uses json modifiers for individual items (that's when an item says +NBT). That's probably a better system to be honest, but it's very different than this tutorial so I can't help you much there.

    Yes.
     
  10. Gamesalive

    Gamesalive Member

    Joined:
    Tuesday
    Posts:
    5
    Hi this is my first time on the gamemaker forum so I hope this works!
    I have a question regarding stack limits. The demo works fine when I move items around the inventory but cant figure put how to make the automatic item adding function check that there is room in the slot.
    Thanks in advance for any suggestions!
     
    Cloaked Games likes this.
  11. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    I can explain it logically at least:

    You want to iterate through the slots of the inventory, taking the item id of the item you want to add and the quantity of items. (Assuming that number of items being added is less than the stack limit for that item).

    On any given slot, you have a few cases:
    - The item id is different than the one you are adding: Move to the next slot (you can't put the item there)
    - The slot is empty: Put the item and the appropriate quantity in that slot and exit
    - The item id matches: Place as many items as you can into that slot and then repeat. If the space left in that slot is enough to fit all of them, exit. Otherwise set that slot to the stack limit (totally filled up) and subtract the number of items needed to fill it from the items you are planning to add, so you can put the rest of the items somewhere else.
    - Finally, there are no slots left: you'll want some sort of exit case for this, like leaving the remaining items on the floor, or prompting the player to choose some items to discard.
     
  12. Gamesalive

    Gamesalive Member

    Joined:
    Tuesday
    Posts:
    5
    Thanks this is exactly the sort of thing I was looking for!
    I was thinking another way could be to use a loop and add 1 item at a time until there are none left to add.
    Thanks for you help!
     
    Cloaked Games likes this.
  13. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    Yeah, that works too.
     
  14. Gamesalive

    Gamesalive Member

    Joined:
    Tuesday
    Posts:
    5
    So i'm still working on adding stack limits when new items are added to the inventory and I think I'm on the right track but for some reason(its probably really obvious) my code sets every inventory slot to the id with an amount of 0. (this is in GM8 by the way, hence the ds_grid_add functions and i replaced enumerators with a list system. I know these functions work properly because they do everywhere else.)
    Here is the code:
    //this script will search for an available slot and add the input item into the inventory
    var iid,amount,slot,inv_width,items;

    iid = argument0;
    amount = argument1;
    slot = 0;
    items = amount;
    inv_width = ds_grid_width(global.inventory)

    {
    while(slot < inv_width)
    {
    //if the slot is either empty or contains a matching id
    if (ds_grid_get(global.inventory,slot,0) == iid) or (ds_grid_get(global.inventory,slot,0) == item('Empty'))
    {
    ds_grid_set(global.inventory,slot,0,iid);
    while(items >0 and ds_grid_get(global.inventory,slot,1)<item_get_stacklimit(iid))
    {
    ds_grid_add(global.inventory,slot,1,1);
    items-=1;
    //check items
    if items <=0
    {
    return true;
    exit;
    }
    }
    }
    slot +=1;
    }
    }
    return false;
     
    Cloaked Games likes this.
  15. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    What exactly happene instead of the intended behavior? On first inspection this code seems A-Okay. I need more information (and I'll look into it with more depth in a few hours when I have time).
     
  16. Gamesalive

    Gamesalive Member

    Joined:
    Tuesday
    Posts:
    5
    Yes I thought it looked ok but what it does is sets every slot to the input id then sets them all to an amount of 0. I'm not sure why?

    If you can have a better way to achieve the result I'm looking for that would be much appreciated because this one has stumped me a bit...
     
    Cloaked Games likes this.
  17. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    731
    I looked in more detail and I honestly cannot figure out what the issue is. I'd check to make sure there's no other code that's overriding that code (or something like running the gain item multiple times). I can't say honesty.

    My code actually works a little differently: namely, the code I used (I just checked because I haven't looked at it for over a year), checks for matching slots first (looping through and adding as many items as possible to a matching slot) and then looks for empty slots to put the rest. This is nice because if there's an empty slot before a matching slot, it'll still put it in the matching slot. So, perhaps you might consider rewriting it, either the same, or a different way such as I described and see what happens?

    I'll update the tutorial to include my solution so you can look at that for reference. Maybe you'll notice something I didn't that results in your code not working?

    EDIT: Updated the tutorial with two more variations of an item gain function, you can see my solution for stack limits under the stack limit section. (Not gonna lie, this tutorial is getting so complicated, it's very hard to do updates without getting confused, can't promise that code would work copy/paste, at least for anyone else using GMS1/2, obviously 8 would need modifications anyways).
     
    Last edited: Oct 19, 2018 at 8:59 PM
  18. Gamesalive

    Gamesalive Member

    Joined:
    Tuesday
    Posts:
    5
    Thanks so much for your help. I will take a look at your updated tutorial. I appreciate all the work you did to help.
     
    Cloaked Games likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice