1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice
  2. Hello Guest! It's with a heavy heart that we must announce the removal of the Legacy GMC Archive. If you wish to save anything from it, now's the time! Please see this topic for more information.
    Dismiss Notice

GMS 2 (Solved) List + Array + Script Args ... syntax troubles

Discussion in 'Programming' started by Energy Engine, Jul 19, 2019.

  1. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    83
    I'm trying to combine lists, arrays and scripts with arguments into one cohesive system.

    Thanks to valuable help I received in this topic, the list and scripts worked. But I've realized now that arguments will apparently be needed. I couldn't properly understand the solution for how arguments could be added to scripts in lists, and arrays were suggested as an alternative. Currently I'm having two issues:

    1) Getting the script inside the list, with arrays as arguments, to be read correctly
    2) Getting a draw text function that can show all types of data. The problem here is with scripts showing as numbers instead of the script resource name.

    Here's what I have:

    create:

    Code:
    list = ds_list_create();
    
    array[0] = scr_debug_msg ///the script
    array[1] = "message works" //argument0 for show_debug_message function
    array[2] = 999 //argument1 for the another show_debug_message
    ds_list_add(list, array);
    step (issue 1):

    Code:
    if keyboard_check_pressed(220)
    {
    if ds_exists(list,ds_type_list)
        {
        for(var i=0; i<ds_list_size(list); i++)
            {
            script_execute(ds_list_find_value(list,array[@ i]));
            }
        }
      
    }
    When I press the key, it gives me the following error:

    Code:
    ___________________________________________
    ############################################################################################
    FATAL ERROR in
    action number 1
    of  Step Event0
    for object oai_new:
    
    (null) argument 1 incorrect type (undefined) expecting a Number (YYGI32)
     at gml_Object_oai_new_Step_0 (line 20) -               script_execute(ds_list_find_value(list,array[@ i]));
    ############################################################################################
    --------------------------------------------------------------------------------------------
    stack frame is
    gml_Object_oai_new_Step_0 (line 20)
    
    The draw code seems to be working fine, but the only problem (issue 2) is getting the script name to show. I can see a number which I assume is the script itself, along with the "message works" text and the 999 figure. I know I can use "script_get_name" separately, but am wondering if its actually possible to maybe squeeze in that along with "string" to form a single piece of code. My current draw code:

    Code:
    if ds_exists(list,ds_type_list)
    {
    for(var i=0; i<ds_list_size(list); i++){
        draw_text(1205, 105 + (24*i), string(list[| i]));
    }
    Any guidance would again be greatly appreciated.

    Many thanks!
     
    Last edited: Jul 19, 2019
    SilentxxBunny likes this.
  2. Homunculus

    Homunculus Member

    Joined:
    Jun 20, 2016
    Posts:
    782
    Using an array to store a script along with its arguments and executing it with script_execute is definitely doable and useful in some specific cases, but what I'm worried about here is that the code has a few macro errors you may need to verify first:

    - The array in the create event probably needs to be a local variable, not an instance variable, otherwise why store it in the list to begin with?
    - In the step event, you'll need to get the array(s) out of the list (due to the above)

    About executing the script:

    script_execute takes a script as first argument, followed by the script arguments. Ideally, assuming you are currently processing the array you created in your code above, it should be something like:
    Code:
    script_execute(array[0], array[1], array[2]);
    
    The problem is that you probably have a different number of arguments for every script, and therefore you can't simply reuse this code for every script in your list since another entry may need to be called differently, like
    Code:
    script_execute(array[0], array[1], array[2], array[3], array[4]);
    
    What you can do is use a switch statement to determine the amount of arguments beforehand and call script execute depending on that value (remembering that one entry in the array is the script itself, so it doesn't count):
    Code:
    var script = array[0];
    var args_count = array_length_1d(array) - 1; //number of arguments for the script
    switch(args_count) {
        case 0: script_execute(script); break;
        case 1: script_execute(script, array[1]); break;
        case 2: script_execute(script, array[1], array[2]); break;
        case 3: script_execute(script, array[1], array[2], array[3]); break;
        //add more if required
    }
    
    About drawing the script name:

    script internally are numbers, that's why when you try to draw a script you don't see the name. You can use script_get_name(script) for that.
     
    Last edited: Jul 19, 2019
    IndianaBones and Energy Engine like this.
  3. IndianaBones

    IndianaBones Member

    Joined:
    Jul 5, 2016
    Posts:
    2,273
    You're trying to pass the contents of the array to the function ds_list_find_value, when it requires an integer position value.

    So when you write this:

    Code:
    script_execute(ds_list_find_value(list,array[@ i]));
    
    Then GMS take the value of "array[@ i]" and uses whatever value that is to find that position in the list.

    At the moment array[@ i], if i = 0, is array[0], which works out to be "scr_debug_message". If scr_debug_message is the first script in your Resource Tree, it will have an integer value of 0.

    So in this case, "array[@ i] = scr_debug_message = 0, your code works out to be:

    Code:
    script_execute(ds_list_find_value(list, 0));
    
    Now, the first item in your list is the variable "array" - which internally is also represented as an integer value. It might be 0 if its the first array you created, or any other number. So script_execute then tries to execute whatever script that refers to. Which is not what you intended.

    However, if "scr_debug_message" is not the first script in your Resource Tree, it might have a value of 3 - but you've only added one item to your list. So when you run ds_list_find_value() with a position of 3, that is non-existing - so you will end up getting and "undefined" returned, and you are trying to then do a script_execute(undefined) which is giving you the error message.

    Anyway, basically what @Catan said is right, you need to extract the array from the list first, then grab the first item of the array, which gives you the script you need to execute, followed by the script parameters, if any. Then use the switch() statement to run script_execute() based on the number of parameters stored in the array.[/code]
     
    Last edited: Jul 19, 2019
    Energy Engine likes this.
  4. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    83
    Thank you @Catan and again @IndianaBones.

    I've used the solution provided by Catan, and it works. However, there are some other major considerations with respect to adding to the list. I'll continue to experiment, and I'll post back soon enough.

    Appreciate the help given so far!
     
    IndianaBones likes this.
  5. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    83
    Alright, bit of a curve ball here.

    With respect to adding to the list, one key item of concern is the following line:
    Code:
    ds_list_add(list, array);
    Ideally, I would have loved it if GMS could allow us to add scripts to a list, with the arguments, as follows:

    Code:
    ds_list_add(list,
    script_X(var1,var2,etc.),
    script_X(varABC,varDEF,etc.),
    )
    But since this isn't doable, arrays have to be used. Originally, I had:

    Code:
    list = ds_list_create();
    
    array[0] = scr_debug_msg ///the script
    array[1] = "message works" //argument0 for show_debug_message function
    array[2] = 999 //argument1 for the another show_debug_message
    ds_list_add(list, array);
    However, this is for one entry only. What if more entries are required? If so, the following is what I think it'd be like (note that I'm using instance variables instead of locals since I'd like the array variables to be accessible at all times):

    Code:
    list = ds_list_create();
    
    array_a[0] = scr_debug_msg
    array_a[1] = "msgA1"
    array_a[2] = "msgA2"
    
    array_b[0] = scr_debug_msg
    array_b[1] = "msgB1"
    array_b[2] = "msgB2"
    
    array_c[0] = scr_debug_anotherscript
    array_c[1] = "msgC1"
    array_c[2] = "msgC2"
    
    ds_list_add(list, array_a,array_b,array_c,...);
    Going by the code posted above by Catan, the problem I see is that there isn't any way for the syntax to "capture" all of the arrays, a,b and c:

    Code:
    var script = array[0];
    var args_count = array_length_1d(array) - 1; //number of arguments for the script
    switch(args_count) {
        case 0: script_execute(script); break;
        case 1: script_execute(script, array[1]); break;
        case 2: script_execute(script, array[1], array[2]); break;
        case 3: script_execute(script, array[1], array[2], array[3]); break;
        //add more if required
    }
    The problem could be addressed if GMS used wildcards, something like array_* to capture any number of array types (say to a-z). But a quick search showed that GMS does not have any such feature at this time. I doubt any for loop will help here either unless I'm mistaken. Even so, I'd wager it'd be a drag on memory to cycle through all the wildcard possibilities.

    Is this the correct approach to adding to the list? Or would there be a need to create another "super" list, and add this one as a "sub" list to the super list? I tried entertaining the idea but hit a brick wall pretty quick.

    Thanks again!
     
  6. RefresherTowel

    RefresherTowel Member

    Joined:
    Jul 13, 2016
    Posts:
    1,217
    Why not just put an array inside the initial array and use that inside the script, something like this:

    Adding to list:
    Code:
    var script_arr[0] = scr_debug;
    script_arr[1] = [arg0,arg1,arg2];
    ds_list_add(list,script_arr);
    
    Executing script:
    Code:
    var script_arr = list[| 0];
    script_execute(script_arr[0],script_arr[1]);
    
    Inside of script:
    Code:
    var script_args = argument[0];
    for (var i=1;i<array_length_1d(script_args);i++) {
       argument[i] = script_args[i-1];
    }
    // Now you have all the arguments you wanted, starting from 1
    
     
    Energy Engine and Homunculus like this.
  7. Homunculus

    Homunculus Member

    Joined:
    Jun 20, 2016
    Posts:
    782
    @RefresherTowel suggestion is a good alternative to the switch method.

    I just want to add that if you are using gms2 you can initialize you arrays like this:

    Code:
    array = [scr_foo, 23, “bar”];
    
     
    Energy Engine likes this.
  8. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    83
    Thanks @RefresherTowel , I tried your suggestion, but there is a slight problem in that at least one argument isn't able to run. The last one ends up being undefined for some reason. Here is what I have:

    Create (note that having var script_arr[0]=scr_debug_msg was giving a syntax error):

    Code:
    list_n=ds_list_create();
    
    var script_arr;
    script_arr[0] = scr_debug_msg;
    script_arr[1] = ["msg1","msg2","msg3"];
    ds_list_add(list_n,script_arr);
    Step:

    Code:
    var script_arr = list_n[| 0];
    script_execute(script_arr[0],script_arr[1]);
    Inside the script:

    Code:
    if (live_call(argument0,argument1,argument2,argument3)) return live_result; //GMLive
    
    var script_args = argument[0];
    for (var i=1;i<array_length_1d(script_args);i++) {
       argument[i] = script_args[i-1];
    }
    
    show_message(argument0);
    
    show_message(argument1);
    show_message(argument2);
    show_message(argument3);
    When I run it, I see the message { {msg1,msg2,msg3} } dialogue, followed by msg1, msg2, but instead of msg3, I get undefined. I understand the first argument (argument0) is showing the list, and the subsequent arguments are showing the next three arguments. So I don't see why "msg3" should come as undefined.

    Inside the script, I tried replacing "script_args[i-1]" with simply "script_args" just to see what would happen. This gives me { {msg1,msg2,msg3} }, skips msg1, shows msg2, msg3 then shows undefined.



    Will keep this in mind. Certainly better than what I was doing before.
     
    Last edited: Jul 21, 2019
  9. Annoyed Grunt

    Annoyed Grunt Member

    Joined:
    Jun 20, 2016
    Posts:
    136
    You need to replace the "<" in your for loop with a "<=". It is currently skipping the last entry of the array, thus returning undefined.
    This said I personally wouldn't go through the problem of reassigning the arguments array, just used the array as provided. It seems like a waste of instructions.
     
    Energy Engine likes this.
  10. RefresherTowel

    RefresherTowel Member

    Joined:
    Jul 13, 2016
    Posts:
    1,217
    ^ That is true, I was assigning the array to the argument array more as a conceptual "this is what it is doing" rather than "you have to do it this way". You can assign properly named vars from the array, or you can simply use the array itself to reference what values you've supplied.
     
  11. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    83
    Thanks, it works correctly now. About reassigning the arguments array, from what I got, I should be able to rewrite the syntax as follows:

    Create:

    Code:
    list_n=ds_list_create();
    
    script_array =[scr_debug_msg,"msg1","msg2","msg3"]
    
    ds_list_add(list_n,script_array)
    The problem I encounter with this is that I can't get the step code to work right because script_execute requires an index as well as a variable to account for the arguments. I tried experimenting with combinations of syntax, but neither worked correctly (best I could get was to get the script to actually run without spitting out errors, but each of the three args showing up as undefined). Not sure if this is what's being referred to or something else.


    NVM, just found under Advanced array functionality: https://docs.yoyogames.com/index.ht.../001_gml language overview/401_06_arrays.html

    Edit: forgot to mark as solved. Thanks to all for your help!
     
    Last edited: Jul 22, 2019

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