GameMaker (Solved) List + Array + Script Args ... syntax troubles

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:
H

Homunculus

Guest
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 by a moderator:
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:
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!
 
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!
 
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
 
H

Homunculus

Guest
@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”];
 
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.

array = [scr_foo, 23, “bar”];
Will keep this in mind. Certainly better than what I was doing before.
 
Last edited:
A

Annoyed Grunt

Guest
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.
 
^ 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.
 
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.
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:
Top