GMS 2 (SOLVED) Iterating through set of objects (or something similar)

Discussion in 'Programming' started by CheeseMyBaby, Jan 10, 2019.

  1. CheeseMyBaby

    CheeseMyBaby Member

    Joined:
    Dec 5, 2018
    Posts:
    59
    Heyo!
    I want mobs to have random drops and I'm very unsure how to go about it.
    I read this thread but it's not quite the way I was hoping to solve it.

    My question is this:
    Let's say I create a bunch of lootable objects and place them all in a "loot group" within the GmS2 IDE,
    would it be possible to iterate through that list (to somehow reference the group from within the game I mean)
    and then pick one object to create.

    If this is a stupid question (I'm fully aware the chances of this being one)... how would you guys go about it?
    I'm guessing there's plenty of you who's done it?
     
  2. sp202

    sp202 Member

    Joined:
    Sep 26, 2016
    Posts:
    961
    I would just add the object IDs of the lootable objects to a list somewhere and use that. I'm pretty sure there is a way to do what you're describing but it seems like an odd method to use.
     
    Gamebot likes this.
  3. Cowlord

    Cowlord Member

    Joined:
    Jun 29, 2017
    Posts:
    55
    I would probably go this route:

    Create parent loot object and all loot is a child of that object.

    then you can do something like:

    Code:
    with (obj_parent) {
        var obj_name = object_get_name(object_index);
        show_debug_message(obj_name);
    }
    This code will cycle through all children of obj_parent and print out it's id. But you can change it to add each child object to an array then use random functions to pick a loot object from the array list.
     
  4. lukbebalduke

    lukbebalduke Member

    Joined:
    Apr 27, 2017
    Posts:
    44
    That is an interesting question, and there are plenty of ways to do that,

    I believe the most efficient one would create a list with all the possible drops, let's say you have a controller_object, and you re going to define the list in its create event

    Code:
    global.list_drop = ds_list_create();
    ds_list_add(global.list_drop, "obj_1", "obj_2", "obj_3");
    Then, create a script file that will allow you to drop objects, call it scr_drop for example

    Code:
    ///@Description drops an object from a given list
    ///@param list
    ///@param x
    ///@param y
    
    var list_id = argument[0];
    var ins_id;
     
    return instance_create_depth( argument[1], argument[2], 0, asset_get_index( ds_list_find_value( list_id, irandom( ds_list_size(list_id) - 1))) );
    This code will get a given list (the list of loots that you've just created), find a random position in that list, get the name of the object and find its resource_index,
    After that, it will instantiate that object with instance_create_depth and return its id.

    You can test using

    Code:
    scr_drop( global.list_drop, mouse_x, mouse_y);
    I also created a project with this code if you want to try it out [HERE]

    Sem título.png
     
  5. RefresherTowel

    RefresherTowel Member

    Joined:
    Jul 13, 2016
    Posts:
    1,101
  6. samspade

    samspade Member

    Joined:
    Feb 26, 2017
    Posts:
    1,870
    While I agree with the other posters that the best version of this is something you code, rather than directly through the IDE. You can essentially do it 'through' the IDE in two ways. The first is by inheritance. If you simply make a parent object and all the lot objects children, then you can do:

    Code:
    
    with (loot_parent) {
        ///do something like for example add it to a ds_list you can shuffle and then choose from
    }
    
    
    While in this case a worse solution in my opinion, you can also loop through objects (or rooms, or really any asset) and get their names as strings and compare those strings. So for example, you could prefix your loot object with loot such as loot_box, loot_bag, etc. Again with objects, I don't really know why you'd do this as it would look something like:

    Code:
    
    with (all) {
        var string_name = object_get_name(id);
        var string_name_prefix = string_copy(string_name, 1, 4);
        if (string_name_prefix = "loot") {
            //do something
        }
    }
    
    
    Way more work for the same thing you can get through parentage or other methods such as a variable. And that version doesn't even have a string length check to avoid errors for objects with a name that is shorter than 4 characters.

    I just mention it because this method is more useful with other types of assets such as rooms, sprites, sounds etc.
     
  7. IndianaBones

    IndianaBones Member

    Joined:
    Jul 5, 2016
    Posts:
    2,068
    The above answers either require the objects to already exist in the room as instancrs, or updating manually a list of strings of object names every time you add/change/delete an object in the resource tree.

    Another way to directly access the resource tree is to understand that all object resources in the tree are represented or indexed by an integer, starting from 0 with the first object in the tree and incrementing by 1 for each following object.

    Note: There is a problem with this solution as well, in that the resource numbering of objects is internal and subject to change if the engine changes. So be aware of that.

    Groups in the resource tree are not accessible, so we have to use our own system.

    We can do this by making two dummy objects, called loot_drop_start and loot_drop_end.

    Put the first one at the start of your group of loot drops and the second one at the end of the loot drop group.

    Now in code we can get the integer index of these two objects using asset_get_index ("loot_drop_start") and same for loot_drop_end.

    This will give two numbers that we can then use to loop through all the assets in between those two resources and build a list of object names automatically.

    Then, whenever you add a new loot drop object between those two dummy objects in the resource tree, they will be automatically be included in the game.

    However, as these are objects only, you can't access any of their values/properties as mentioned above, without first creating them as instances.

    So then you are left with having to create hidden instances of all the objects so you can read their values and determine their drop rate etc...

    The best long term solution would be more I the direction of having an external file that contains all the loot items and their drop rate that can be loaded by the game, either a JSON or ini file would be suitable while you are still developing the game. Then all you need to do to update the drop rate info is edit the file and re-run the game.

    Especially useful if you are collaborating with more than one person, they can change values and test them without needing a recompile of the game to be done.

    This way you could just have one loot drop object, and once you have chosen a random loot object based on the data in the file you loaded, just apply those properties to it.

    But then you still have to manually setup the graphics for the loot item if you want them all to be unique. A way around that would be making the loot drop object have a generic icon based on its type.

    In summary of this long post, there's a lot of ways you could do it, using the resource tree probably isn't the best way but it can be done.
     
    RefresherTowel likes this.
  8. CheeseMyBaby

    CheeseMyBaby Member

    Joined:
    Dec 5, 2018
    Posts:
    59
    Lots of informational replies. I think I have what I need to be able to write something up.
    Thank you all for your time and input. It's highly appreciated!
     
    IndianaBones 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