• Hey! Guest! The 39th GMC Jam will take place between November 26th, 12:00 UTC and November 30th, 12:00 UTC. Why not join in! Click here to find out more!

Legacy GM Nifty scripts I call SalTools: new jarray!

S

Salvakiya

Guest
SalTools

hey all... here are some scripts which are a part of every project I make. If you see a way they can be optimised please let me know! Also keep in mind some of these are merely shortcuts or things which make my life easier when I code. This does not mean they are the fastest way to do things. you should always be aware of the overhead of calling such functions. They help me keep my code more organised and when I run into performance issues I can rewrite my code without the shortcuts.

usage:
Code:
my_string_length = len("hello")
my_array_length = len(array(1,2,3,4,5,4,3))
script:
Code:
///len(type)// returns length of given array or string
/*
    For array returns double;
    For array2d returns array of length 2. defaults to MAX possible size.

    returns -1 if no valid type found
*/
var type = argument[0];

if is_string(type){return string_length(type)}else
if is_array(type){
    //is it 1d?
    var ah = array_height_2d(type);
    var al = array_length_2d(type,0);
    if ah == al{/*yes return 1d*/return al}else{
        //return 2d
        var m = 0;
        for (i=0; i<ah; i+=1)
        {
            al = array_length_2d(type,i);
            m = max(al,m);
        };
        //return size in array len: return[0],return[1]
        return array(ah,m);
    }
}

return -1;
usage:
Code:
obj = new(object0)
obj = new(object0,x,y)
obj = new(object0,x,y,z)
script:
Code:
///new( object, [ x[, y[, z] );
if( argument_count == 0 || argument_count > 4  ){ show_error("Incorect arguments supplied", true); }
var args = array( argument[0], 0, 0, 0);
for( var i = 1; i < argument_count; i ++ ){
    args[ i ] = argument[i];
}
with( instance_create( args[1], args[2], args[0]) {
    z = args[3];
    return id;
}
Code:
#define print
///print(str message[,bool debug]);
var message = "";
for (var i=0; i<argument_count; i+=1)
{
    message+=string(argument[i]);
};
show_debug_message(message)
Code:
///asset_exists(str name) returns bool
//shortened thanks to Freddy Jones =)
return (asset_get_index(argument[0]) != -1 );
Code:
///array(val,val,val,val,val,val,val,ect);
var arr;
for (i=0; i<argument_count; i+=1)
{
    arr[i] = argument[i];
};
return arr;
Thanks to Freddy Jones for the fix!
Code:
///jarray(json_list)
var map = json_decode(argument0);
// if the json could not be parsed json_decode returns -1
if( map == -1 ){ show_error("Json could not be read.", false);}
// if it was a list, the list is found in "default
var list = ds_map_find_value(map, "default");
var len = ds_list_size(list);
for (var i = 0, arr; i < len; i ++ ){
    arr[i] = list[|i];
}
ds_map_destroy(map);
ds_list_destroy(list);
return arr;

If you have any questions or comments let me know!



Edit: thanks to Freddy Jones for help with multiple of these scripts!
Edit: added jarray.. usage arr = jarray("['a','b','c',1,2,3]"); for use with arrays larger than 16
Edit: fixed array to be more efficient on windows. thanks to Yal for sharing! https://forum.yoyogames.com/index.php?threads/initialize-an-array-in-one-line.4232/#post-32510
 
Last edited:

Freddy Jones

Your Main Detective
From what I read, I don't believe ,when it comes to data structures, LEN will work correctly. It may seem like it, but it is because of misconception. Reason: if you make a list and grid, the create function for both of them will return 0 (on first use). With that in mind, there's no way to tell for sure what that value is without context. The reason this doesn't happen to arrays is because they act more like memory pointers that GM can interpret itself.

The new(object) code just appears to be a non useful trivial wrapper for instance_create. I've attempted something like this myself in the past but the caveat you've pointed out renders this specific case useless.

Your print function looks pretty much exactly how I have my "log" function. Pretty handy I'd say so myself.


Asset exists, if it works, could easily be shortened as:
Code:
return (asset_get_index(argument[0]) != -1 );
The array function is pretty nice, it's kind of just another syntactical sugar function but still useful. I can't recall exactly what it is, but I believe because your returning an array you'll have the overhead of copying and such - but at max 16 inputs. I've never had a use for something like this in particular but it works.


- written from multiple phone so kind of hard to go back through it.
 
Last edited:
S

Salvakiya

Guest
From what I read, I don't believe ,when it comes to data structures, LEN will work correctly. It may seem like it, but it is because of misconception. Reason: if you make a list and grid, the create function for both of them will return 0 (on first use). With that in mind, there's no way to tell for sure what that value is without context. The reason this doesn't happen to arrays is because they act more like memory pointers that GM can interpret itself.

The new(object) code just appears to be a non useful trivial wrapper for instance_create. I've attempted something like this myself in the past but the caveat you've pointed out renders this specific case useless.

Your print function looks pretty much exactly how I have my "log" function. Pretty handy I'd say so myself.


Asset exists, if it works, could easily be shortened as:
Code:
return (asset_get_index(argument[0]) != -1 );
The array function is pretty nice, it's kind of just another syntactical sugar function but still useful. I can't recall exactly what it is, but I believe because your returning an array you'll have the overhead of copying and such - but at max 16 inputs. I've never had a use for something like this in particular but it works.


- written from multiple phone so kind of hard to go back through it.
not sure I follow what you mean about the len script. The new script I use mostly because I have lots of instances where I dont need to assign an x and y value and I would rather not write instance_create(0,0,object) when I can just write new(object). I find it easier to read as well. In the case where I need to assign a Z value it is nice because I can keep it all on one neat line new(object,x,y,z). Thanks for the tip on Asset Exists! idk why I did not think of that. My new code style comes from my wishing that GM was a bit more like python =P
 

Freddy Jones

Your Main Detective
Code:
if ds_exists(type,ds_type_list){return ds_list_size(type)}else
if ds_exists(type,ds_type_map){return ds_map_size(type)}else
if ds_exists(type,ds_type_priority){return ds_priority_size(type)}else
if ds_exists(type,ds_type_queue){return ds_queue_size(type)}else
if ds_exists(type,ds_type_stack){return ds_stack_size(type)}else
if ds_exists(type,ds_type_grid){return array(ds_grid_width(type),ds_grid_height(type))}
This code from your "len" function is error prone. First, the value you will be providing to this function is not a type. Second, the reason ds_exists needs the "ds_type_*", is because it can't differentiate the difference between a map, priority, or list ETC. So basically, this set of functionality is impossible to implement and "ds_exists" by itself is as far as you can go with trying to know if something exists. It will cause errors.


You'll find sooner or later that the "new" function is impractical. It is, nicer looking than instance_create, but semantics is more important than syntax. And I figured the use case was of that reasoning, I wish a lot of things were a lot more like JavaScript but everyone hates it lol.

Your new script could be written as follows, to reduce the number of checks. Also, argument count will never be less than 0 so that's an unnesssary condition to check for.
Code:
///new( object, [ x[, y[, z] );
if( argument_count == 0 || argument_count > 4  ){ show_error("Incorect arguments supplied", true); }
var args = array( argument[0], 0, 0, 0);
for( var i = 1; i < argument_count; i ++ ){
    args[ i ] = argument[i];
}
with( instance_create( args[1], args[2], args[0]) {
    z = args[3];
    return id;
}
When I say "find sooner or later" that it's impractical, I mean you'll have situations where it makes more sense to disregard the function altogether because of the necessary overhead and start using more useful scripts that act more like instantiaters you'd find in C++.

For example:
Code:
///my_system_controller_create( [] )
with( instance_create( 0, 0, obj_controller_thing) ){
    // perform some actions here that should be
    // figured out with the arguments provided on create.
}

I hope you like my feedback!
 
S

Salvakiya

Guest
Code:
if ds_exists(type,ds_type_list){return ds_list_size(type)}else
if ds_exists(type,ds_type_map){return ds_map_size(type)}else
if ds_exists(type,ds_type_priority){return ds_priority_size(type)}else
if ds_exists(type,ds_type_queue){return ds_queue_size(type)}else
if ds_exists(type,ds_type_stack){return ds_stack_size(type)}else
if ds_exists(type,ds_type_grid){return array(ds_grid_width(type),ds_grid_height(type))}
This code from your "len" function is error prone. First, the value you will be providing to this function is not a type. Second, the reason ds_exists needs the "ds_type_*", is because it can't differentiate the difference between a map, priority, or list ETC. So basically, this set of functionality is impossible to implement and "ds_exists" by itself is as far as you can go with trying to know if something exists. It will cause errors.


You'll find sooner or later that the "new" function is impractical. It is, nicer looking than instance_create, but semantics is more important than syntax. And I figured the use case was of that reasoning, I wish a lot of things were a lot more like JavaScript but everyone hates it lol.

Your new script could be written as follows, to reduce the number of checks. Also, argument count will never be less than 0 so that's an unnesssary condition to check for.
Code:
///new( object, [ x[, y[, z] );
if( argument_count == 0 || argument_count > 4  ){ show_error("Incorect arguments supplied", true); }
var args = array( argument[0], 0, 0, 0);
for( var i = 1; i < argument_count; i ++ ){
    args[ i ] = argument[i];
}
with( instance_create( args[1], args[2], args[0]) {
    z = args[3];
    return id;
}
When I say "find sooner or later" that it's impractical, I mean you'll have situations where it makes more sense to disregard the function altogether because of the necessary overhead and start using more useful scripts that act more like instantiaters you'd find in C++.

For example:
Code:
///my_system_controller_create( [] )
with( instance_create( 0, 0, obj_controller_thing) ){
    // perform some actions here that should be
    // figured out with the arguments provided on create.
}

I hope you like my feedback!
did some tests and I see what you mean... I would think the gm help doc is misleading in this case
"With this function you can check to see if a data structure of the given type exists. You supply the "index" value (as held in a variable) and the ds "type", which can be any of the constants listed below, and the function will return true if the data structure exists and false otherwise. "

basically there is no real need for the ds_type_* then... You potentially saved me hours of debugging!

Also I know what you mean about new. But knowing me if I need performance I will just keep new and change it to return instance_create(argument[0],argument[1],argument[2]) because I am lazy =P.



cheers!
 

Freddy Jones

Your Main Detective
did some tests and I see what you mean... I would think the gm help doc is misleading in this case
"With this function you can check to see if a data structure of the given type exists. You supply the "index" value (as held in a variable) and the ds "type", which can be any of the constants listed below, and the function will return true if the data structure exists and false otherwise. "

basically there is no real need for the ds_type_* then... You potentially saved me hours of debugging!

Also I know what you mean about new. But knowing me if I need performance I will just keep new and change it to return instance_create(argument[0],argument[1],argument[2]) because I am lazy =P.



cheers!
You'll get some run-time errors if you use return instance_create(argument[0],argument[1],argument[2]) to fill in argument[1], argument[2], without actually supplying those arguments. Game maker won't implicitly define them for you! (Last time I checked). And no problem! I like to help out, good luck programming.
 
S

Salvakiya

Guest
You'll get some run-time errors if you use return instance_create(argument[0],argument[1],argument[2]) to fill in argument[1], argument[2], without actually supplying those arguments. Game maker won't implicitly define them for you! (Last time I checked). And no problem! I like to help out, good luck programming.
yea I know that much. I just hate typing instance_create =P. thanks again m8!
 
Top