* website skeleton * updated bunder to 2.0, added caching * fix missing plugins? * enable deploy for the branch, try to save cache * need to use relative path? * fix missing css * use doc theme * really enable doc theme? * mayeb this time * come on baby * how about now * please ? * pretty please * ehhh * working theme * added hooks * formatting * formatting 2 * added doc yaml from bgforge mls 1.0.7 * no need for nav order * link reference * hooks on top * added global scripts * pages are generated, exclude them * generate site * pip3 ? * maybe now * hooks page is generated automatically * added table of contents to pages * don't waste so much space * switch highlight classes * mark functions as code in description * more formatting * reformat doc with python * loaded offsets * opcode is loaded into yaml, txt no longer necessary * mark unsafe functions * restore hooks page * clarification * deduplicated hooks doc * saner TOC * typo * move more docs * hook scripts doc is now in md * arrays doc is now in md * added data types page * added more info about old behaviour * minor formatting issues * moved more function docs to yaml * all sfall functions docs are transpiled to yaml format * formatting * fix format * add subcategory support * simplified yaml format, added structure doc * simplified structure and added clarification * generated a separate page for hook types * formatting * disambiguation * format clarification * move get_map* to subcategory: doc is not relevant for other functions * simple permalink * fix links * included more info on the main page * more clarification * rename offset > opcode * try to get more sensible baseurl * added best practices page * what's up with the slashes * allow parent pages with no content * separate docs for direct memory access functions * added latest functions * fixed hook types link * move get_explosion_damage to macros * removed duplicated comment * removed old comments * added hook ids * lowercase sfall * more sfall lowercasing * added proper permalinks * changes from mr.stalin * fix typos * clarification * fix direct memory access page * fixed top navlink * fixed urls * checked sfallgv.sav, it's really not bloating much * format clarification * shorter name * add mixed data type, sort * add proc type, link hooks functions * use same terminology * added bool * rearranged index * added unsafe label * move to root * add stats * more upper/lowercase * should work now * added build status * added combat category, added description for modified_ini, moved global script functions into a subcat * special note for set_self * typo * enable children * cleanup * move lists to arrays * show header filename for macro instead * rearrange more items to be more intuitive * build on bionic * separate object manipulation * added object manipulation link to home * typo * formatting * Added a note about charges * punctuation * formatting * moved floor2 to math * changed label color * moved art and appearance to animations * name too long * search note * moved exex_map_update to maps category * moved more functions from other to skills * too much blue * formatting * moved art_cache_clear to art section * empathize that var name must be exactly 8 characters long * update usages for inc_npc_level * separate objects, scripts and variables * updated url * moved get_string_pointer to strings * updated add_extra_msg_file doc * typo * latest doc updates from develop * updated default layout from upstream * applied local changes: subcategory list * remove unnecessary backticks * added new functions * fix STD_PROCEDURE_END display * formatting * don't fail on missing hook id * formatting * updated doc from upstream * added optimization and sslc pages * order ssl and optimization pages below home * really order optimization on top * merge objects_in_radius variants * updated from upstream * tone down link color * fixed formatting for updated theme * updated travis for ruamel * added favicon * restored separator between functions * updated functions.yml * updated sfall functions * rearranged some window and object function * hook updates, pre-arg renaming * hook args renumbering * merged upstream * added new hooks and functions from upstream * remove the long-winded note about macro * switch to gha for jekyll deployment * sudo for deps * try to fix ruamel missing * switch build to master only, ref https://github.com/phobos2077/sfall/pull/241#discussion_r580365212 * update status badge for https://github.com/phobos2077/sfall/pull/241
11 KiB
layout, title, nav_order, has_children, permalink
| layout | title | nav_order | has_children | permalink |
|---|---|---|---|---|
| page | Arrays | 2 | true | /arrays/ |
Arrays
{: .no_toc}
sfall introduces new method of storing variables - arrays.
Array is basically a container which can store variable number of values (elements). Each element in array can be of any type. Arrays can be extremely useful for some more advanced scripting, in conjunction with loops. See array function reference [here]({{ site.baseurl }}/array-functions/).
- TOC {:toc}
Arrays concept
Array elements are accessed by index or key. For example:
// this code puts some string in array "list" at index 5:
list[5] := "Value";
There are 2 different types of arrays currently available:
-
Lists - a set of values with specific size (number of elements), where all elements have numeric indexes starting from zero (0) up to array length minus one.
For example:
// this creates list with 3 elements. Element "A" has index 0, element "B" has index 1, element "C" - 2 list := ["A", "B", "C"];Limitations:
- all indexes are numeric, starting from 0;
- to assign value to a specific index, you must first resize array to contain this index (for example, if list is of size 3 (indexes from 0 to 2), you can't assign value to index 4 unless you change list size to 5 first).
-
Maps (or associative arrays) - a set of key=>value pairs, where all elements (values) are accessed by corresponding keys. Differences from list:
- maps don't have specific size (to assign values, you don't need to resize array first);
- keys, just like values, can be of any type (but avoid using -1 as array keys or you won't be able to use some functions reliably).
Both array types have their pros and cons and are suited for different tasks.
Arrays syntax
Basically arrays are implemented using number of new operators (scripting functions). But for ease of use, there are some new syntax elements:
-
Accessing elements. Use square brackets:
display_msg(arr[5]); mymap["price"] := 515.23; -
Alternative accessing for maps. Use dot:
display_msg(mymap.name); mymap.price := 232.23; -
Array expressions. Create and fill arrays with just one expression:
// create list with 5 values [5, 777, 0, 3.14, "Cool Value"] // create map: {5: "Five", "health": 50, "speed": 0.252}NOTES: Make sure to call
fix_arrayif you want new array to be available in the next frame orsave_arrayif you want to use it for a longer period (see next section for details). -
Iterating in loop. Use "foreach" key word like this:
foreach (item in myarray) begin // this block is executed for each array element, where "item" contains current value on each step end // alternative syntax: foreach (key: item in myarray) begin // "key" will contain current key (or numeric index, for lists) end
See "Script editor\docs\sslc readme.txt" file for full information on new SSL syntax features.
Storing arrays
Apart from lists/maps arrays are divided by how they are stored. There a 3 types of arrays:
-
Temporary. They are created using
temp_arrayfunction or when using array expressions. Arrays of this type are auto-deleted at the end of the frame. So, for example, if you have a global script which runs at regular intervals, where you create temp_array, it will not be available next time your global script is executed. -
Permanent. They are created using
create_arrayfunction orfix_array(from pre-existing temporary array). This type of arrays are always available (by their ID) until you start a new game or load a saved game (at which point they are deleted). -
Saved. If you want your array to really stay for a while, use function
save_arrayto make any array "saved". However, they are, like permanent arrays, "deleted" from memory when loading game. In order to use them properly, you must load them from the savegame usingload_arraywhenever you want to use them. Example:
variable savedArray;
procedure start begin
if game_loaded then begin
savedArray := load_array("traps");
end else begin
foreach trap in traps begin
....
end
end
end
Practical examples
Use arrays to implement variable-argument procedures
// define it
procedure give_item(variable critter, variable pidList) begin
foreach (pid: qty in pidList) begin
give_pid_qty(critter, pid, qty);
end
end
// call it:
call give_item(dude_obj, {PID_SHOTGUN: 1, PID_SHOTGUN_SHELLS: 4, PID_STIMPAK: 3});
Create arrays of objects (maps) for advanced scripting
variable traps;
procedure init_traps begin
// just a quick example, there is a better way of doing it...
traps := load_array("traps");
if (traps == 0) then begin
traps := [];
save_array("traps", traps);
end
foreach k: v in traps begin
traps[k] := load_array("trap_"+k); // each object is stored separately
end
end
procedure add_trap(variable trapArray) begin
variable index;
index := len_array(traps);
save_array("trap_"+k, trapArray);
array_push(traps, trapArray);
end
// use them:
foreach trap in traps begin
if (self_elevation == trap["elev"] and tile_distance(self_tile, trap["tile"]) < trap["radius"]) then
// kaboom!!!
end
end
Array operators reference
*mixed means any type
-
int create_array(int size, int flags):- creates permanent array (but not "saved")
- if size is >= 0, creates list with given size
- if size == -1, creates map (associative array)
- if size == -1 and flags == 2, creates a "lookup" map (associative array) in which the values of existing keys are read-only and can't be updated. This type of array allows you to store a zero (0) key value
- NOTE: in earlier versions (up to 4.1.3/3.8.13) the second argument is not used, just use 0
- returns arrayID (valid until array is deleted)
-
int temp_array(int size, int flags):- works exactly like
create_array, only created array becomes "temporary"
- works exactly like
-
void fix_array(int arrayID):- changes "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames)
-
void set_array(int arrayID, mixed key, mixed value):- sets array value
- if used on list, "key" must be numeric and within valid index range (0..size-1)
- if used on map, key can be of any type
- to "unset" a value from map, just set it to zero (0)
- NOTE: to add a value of 0 for the key, use the float value of 0.0
- this works exactly like statement:
arrayID[key] := value;
-
mixed get_array(int arrayID, mixed key):- returns array value by key or index
- if key doesn't exist or index is not in valid range, returns 0
- works exactly like expression:
(arrayID[key])
-
void resize_array(int arrayID, int size):- changes array size
- applicable to maps too, but only to reduce elements
- there are number of special negative values of "size" which perform various operations on the array, use macros
sort_array,sort_array_reverse,reverse_array,shuffle_arrayfromsfall.hheader
-
void free_array(int arrayID):- deletes any array
- if array was "saved", it will be removed from a savegame
-
mixed scan_array(int arrayID, mixed value):- searches for a first occurence of given value inside given array
- if value is found, returns it's index (for lists) or key (for maps)
- if value is not found, returns -1 (be careful, as -1 can be a valid key for a map)
-
int len_array(int arrayID):- returns number of elements or key=>value pairs in a given array
- if array is not found, returns -1 (can be used to check if given array exist)
-
mixed array_key(int arrayID, int index):- don't use it directly; it is generated by the compiler in foreach loops
- for lists, returns index back (no change)
- for maps, returns a key at the specified numeric index (don't rely on the order in which keys are stored though)
- can be checked if given array is associative or not, by using index (-1): 0 - array is list, 1 - array is map
-
int arrayexpr(mixed key, mixed value):- don't use it directly; it is used by compiler to create array expressions
- assigns value to a given key in an array, created by last
create_arrayortemp_arraycall - always returns 0
-
void save_array(mixed key, int arrayID):- arrayID is associated with given "key"
- array becomes permanent (if it was temporary) and "saved"
- key can be of any type (int, float or string)
-
int load_array(mixed key):- load array from savegame data by the same key provided in
save_array - arrayID is returned or zero (0) if none found
- load array from savegame data by the same key provided in
Backward compatibility notes
For those who used arrays in their mods before sfall 3.4:
- There is an INI parameter
arraysBehaviorin "Misc" section of ddraw.ini. If set to 0, all scripts which used sfall arrays before should work. This basically changes thatcreate_arraywill create permanent arrays which are "saved" by default and their ID is also permanent. It is 1 by default. - If
arraysBehaviour=0: Arrays are created and manipulated with thexxx_arrayfunctions. An array must first be created withcreate_arrayortemp_array, specifying how many data elements the array can hold. You can store any of ints, floats and strings in an array, and can mix all 3 in a single array. The id returned bycreate/temp_arraycan then be used with the other array functions. Arrays are shared between all scripts. (i.e. you can callcreate_arrayfrom one script, and then use the returned id from another script.) They are also saved across savegames. You must remember to free any arrays you create withcreate_arraywhen you are done with them, or you will leak memory. arrays created withtemp_arraywill be automatically freed at the end of the frame. These functions are safe, in that supplying a bad id or trying to access out of range elements will not crash the script.create_arrayis the only function that returns a permanent array, all other functions which return arrays (string_split,list_as_arrayetc,) all return temp arrays. You can usefix_arrayto make a temp array permanent. - How savegame compatibility is handled? Saved arrays are stored in sfallgv.sav file (in savegame) in new (more flexible) format, just after the old arrays. So basically, when you load older savegame, sfall will load arrays from old format and save them to new format on next game save. If you load savegame made with sfall 3.4 using sfall 3.3 (for example), game shouldn't crash, but all arrays will be lost.
- Previously you had to specify size in bytes for array elements. This parameter is now ignored and you can store strings of arbitrary length in arrays.