Little Helpers - Grisgram/gml-raptor GitHub Wiki

This is a group of helper functions that did not fit anywhere else and are too few (and too small) to get their own script for each.

is_between
is_between_ex

Test, if the specified value is between the lower_bound and the upper_bound, where
is_between tests the range including both bounds, and
is_between_ex tests excluding both bounds.

/// @function			is_between[_ex](val, lower_bound, upper_bound)
/// @description		test if a value is between lower and upper bounds
/// @param {real/int} value
/// @param {real/int} lower_bound
/// @param {real/int} upper_bound
/// @returns {bool} y/n
function is_between(val, lower_bound, upper_bound) {
function is_between_ex(val, lower_bound, upper_bound) {

is_any_of

/// @function			is_any_of(val, ...)
/// @description		Specify any number of parameters after "val".
///				Determines if val is equal to any of them.
/// @param {any} val	The value to find
/// @param {any} ...	List of values to search
/// @returns {bool}	y/n
function is_any_of(val1, val2, val3, ) {

percent
percent_mult

Gets, how many % value is of total.
percent returns the full value (Example: val 30, total 50 -> returns 60(%)) and
percent_mult returns a multiplier for the value, so 0.6 instead of 60.

/// @function		percent(val, total)
/// @description	Gets, how many % "val" is of "total"
/// @param {real} val	The value
/// @param {real} total	100%
/// @returns {real}	How many % of total is val. Example: val 30, total 50 -> returns 60(%)
function percent(val, total) {
function percent_mult(val, total) {

is_child_of

GameMaker's object_is_ancestor has a little flaw: It returns false if the object is exactly the ancestor. If you test object_is_ancestor(myGameObject, myGameObject) you receive false because it is not derived from myGameObject.
This function here will return true in this case (and also uses object_is_anchestor, so you get the same results, except that the case child==parent also returns true).

/// @function					is_child_of(child, parent)
/// @description				True, if the child is exactly parent type or derived from it
/// @param {object_index} child
/// @param {object} parent
/// @returns {bool}
function is_child_of(child, parent) {

run_delayed
run_delayed_ex
run_delayed_exf

Executes the specified func after a waiting time of delay frames.

NOTE: The Animation ListPool is used to count the frames, as the functionality uses an internal raptor function to achieve the delay. Keep in mind, that calling animation_abort_all on the owner specified here will also stop this delayed execution.
run_delayed_ex runs the function exclusively, and invokes animation_abort_all before starting the waiter.
run_delayed_exf runs the function exclusively, and invokes animation_finish_all before starting the waiter.

See abort() vs finish(), if you are unsure, what that means.

/// @function		run_delayed[_ex](owner, delay, func, data = undefined)
/// @description	Executes a specified function in <delay> frames from now.
///			Behind the scenes this uses the __animation_empty function which
///			is part of the ANIMATIONS ListPool, so if you clear all animations,
///			or use animation_run_ex while this is waiting for launch, 
///			you will also abort this one here.
///			Keep that in mind.
/// @param {instance} owner	The owner of the delayed runner
/// @param {int} delay		Number of frames to wait
/// @param {func} func		The function to execute
/// @param {struct} data	An optional data struct to be forwarded to func. Defaults to undefined.
function run_delayed(owner, delay, func, data = undefined) {
function run_delayed_ex(owner, delay, func, data = undefined) {
function run_delayed_exf(owner, delay, func, data = undefined) {

method_exists
invoke_if_exists

/// @function 		method_exists(_instance, _method)
/// @description 	Checks, whether a method with the specified name exists in _instance
/// @returns {bool}	True, if a method with that name exists, otherwise false
function method_exists(_instance, _method) {
/// @function 		invoke_if_exists(_instance, _method, ...)
/// @description 	Invoke the method, if it exists, with all arguments specified after the
///			_instance and _method arguments.
///			NOTE: GameMaker supports a maximum of 16 arguments, 2 are already used for
///			_instance and _method, so this leaves a maximum of 14 arguments for your call
/// @returns {any} 	The return value of the method or undefined, if the method does not exist
function invoke_if_exists(_instance, _method) {

with_tag

/// @function 		with_tag(_tag, _func, _data = undefined)
/// @description 	Executes the specified function for all object instances that are tagged
///			with the specified tag.
///			NOTE: The function is temporary bound to the instance, so
///			the code IN the function will run in the scope of the instance!
///			You may also specify any _data object to be sent into each of 
///			the invoked functions
function with_tag(_tag, _func, _data = undefined) {

collider_first
collider_cleanup

/// @function collider_first()
/// @description Checks, if this is the first collision between self and other
///		 (means: there has not been the same collision in the previous frame),
///		 and returns true, if that's the case.
///		 The function has no arguments, as it uses "self" and "other", like you
///		 would, when coding in the collision event
function collider_first() {
/// @function collider_cleanup()
/// @description This function is called in the "Room End" event of the RoomController.
///		 It removes all cached collisions and works like a full reset.
function collider_cleanup() {

construct_or_invoke

/// @function construct_or_invoke(_script, args...)
/// @description Tries to create the specified function (succeeds, if it is a constructor),
///		 and if that fails, just invokes it and returns the result.
///		 All arguments you specify are sent to the function.
function construct_or_invoke(_script, arg1, arg2, arg3,) {

struct_join
struct_join_into
struct_join_no_rebind
struct_join_into_no_rebind

Using the functions ending with _no_rebind will not rebind methods in the structs to the new struct, instead the method pointers are just copied.

/// @function		struct_join(structs...)
/// @description	Joins two or more structs together into a new struct.
///			NOTE: This is NOT a deep copy! If any struct contains other struct
///			references, they are simply copied, not recursively converted to new references!
///			ATTENTION! No static members can be transferred! Best use this for data structs only!
/// @param {struct...} any number of structs to be joined together
function struct_join(structs) {
/// @function		struct_join_into(target, sources...)
/// @description	Integrate all source structs into the target struct by copying
///			all members from source to target.
///			NOTE: This is NOT a deep copy! If source contains other struct
///			references, they are simply copied, not recursively converted to new references!
///			ATTENTION! No static members can be transferred! Best use this for data structs only!
function struct_join_into(target, sources) {

string_match

A comfortable wildcard engine, allowing you to create mask- oder filter-expressions.

Filter character is * and can be placed like this:

Position Description Example
* at the start of the string Means "string ends with" *llo -> hello
* at the end of the string Means "string starts with" he* -> hello
* at both ends Means "contains" *ell* -> hello
/// @func	string_match(str, wildcard_str)
/// @desc	Checks whether a string matches a specific wildcard string.
///		Wildcard character is '*' and it can appear at the beginning,
///		the end, or both.
///		* at the beginning means "ends_with" (hello -> *llo)
///		* at the end means "starts_with" (hello -> he*)
///		* on both ends means "contains" (hello -> *ell*)
///		NOTE: if no '*' is in wildcard_str, then a == exact match counts!
///		Examples:
///		string_match("hello", "hel*") -> true
///		string_match("hello", "*hel*") -> true
///		string_match("hello", "*hel") -> false
function string_match(str, wildcard_str) {

string_interpret

This is one of the most powerful helper functions. It interprets a string at runtime against a living object or class instance and returns, whether the specified variable in the instance has the value you are looking for.

/// @func	string_interpret(_str, _instance, _with_inheritance = true)
/// @desc	Interprets a string that may contain dot-notation, like
///		"myinst.data.name:value" and interprets this against the supplied instance.
///		If _str does not contain a dot-notation, name_of(_instance,false) is compared against _str.
///		If _str ends with "()", the last part of the chain is considered a function and will be invoked
///		on the instance. ONLY PARAMETERLESS FUNCTIONS ARE SUPPORTED! (like ".get_name()")
///		If _with_inheritance is true, interpret also succeeds if the _instance is a child of the
///		type name of _str. It is automatically detected, whether _instance is an object or class instance.
///		Example: 
///		- You are ("self") an object or an instance of type Enemy 
///		  that contains .data.name with a value of "Mummy"
///		- You call string_interpret("Enemy.data.name:Mummy", self) and it returns true, because
///		  your .data.name == "Mummy"
///		- Would you call it with ("Enemy.data.name:Scarab", self) it would return false.
///		This function is very useful to connect variables/members of objects in strings, like when
///		you read data from json and want to compare it with runtime data of your living objects.
///		Boolean conversion is automatically in place, ":true" and ":false" are compared with "1" and "0"
///		(which is gml default)
⚠️ **GitHub.com Fallback** ⚠️