The functions in lib_array are all aimed at making it easier to work with arrays, WEIDU's powerful-but-awkward datatype. Unless otherwise noted, they can handle arrays with up to five keys (one limitation of WEIDU is that you can't readily write code to handle an arbitrary number of keys). Unless otherwise noted, all functions here are dimorphic.
You can get an array printed out on the screen using array_echo:
LAF array_echo STR_VAR array=spell_array END
This is unlikely to be useful in live code, but it's good for debugging.
The 'array_contains' function tells you whether an array contains an entry with a given key and/or given value. For instance, suppose we define this array:
ACTION_CLEAR_ARRAY test_array
ACTION_DEFINE_ASSOCIATIVE_ARRAY test_array BEGIN
Minsc=>"awesome"
Anomen=>"annoying"
Sarevok=>"Treacherous; watch out for him"
END
Then this command returns value=1:
LAF array_contains STR_VAR array=test_array key="Minsc" RET value END
And so does this one:
LAF array_contains STR_VAR array=test_array val="annoying" RET value END
LAF array_contains STR_VAR array=test_array key="Minsc" val="awesome" RET value END
But this one returns value=0:
LAF array_contains STR_VAR array=test_array key="Minsc" val="annoying" RET value END
(There is an entry with key='Minsc' and an entry with value='annoying', but no entry with both.)
For key checks, the difference between using array_contains and just doing VARIABLE_IS_SET is that array_contains checks the actual array, whereas VARIABLE_IS_SET checks the underlying struct. If you CLEAR_ARRAY the test array above, array_contains will report that there is no entry with key 'Minsc', whereas VARIABLE_IS_SET "test_array_Minsc" will return true.
array_contains is case-sensitive. In multi-key arrays it checks only the first key.
The array_length function just tells you how many entries there are in an array:
LAF array_length STR_VAR array=test_array RET value END
will, if run on the above array, return value=3.
The array_keys function returns arrays (in k=>_ format) of the various levels of its keys. For instance, consider this array:
ACTION_CLEAR_ARRAY test_array
ACTION_DEFINE_ASSOCIATIVE_ARRAY test_array BEGIN
Minsc,awesome => 1
Anomen,awesome=>0
Anomen,annoying =>1
Sarevok,treacherous=>0
END
If you do
LAF array_keys STR_VAR array=test_array RET keys1 keys2 END
then keys1 will be an array with keys 'Minsc', 'Anomen', 'Sarevok' and keys2 will be an array with keys 'awesome', 'annoying', 'treacherous'.
The array_split function takes an array and splits it into two arrays, based on criteria specified by the SFO-standard-format functions 'match_key' and/or 'match_value'. For instance, consider this code:
ACTION_CLEAR_ARRAY npc_class
ACTION_DEFINE_ASSOCIATIVE_ARRAY npc_class BEGIN
Minsc=>ranger
Anomen=>cleric
Sarevok=>fighter
Jan=>mage_thief
Aerie=>cleric_mage
END
DEFINE_PATCH_FUNCTION is_annoying
STR_VAR arguments=""
RET value
BEGIN
PATCH_MATCH "%arguments%" WITH
Anomen Jan Aerie BEGIN
value=1
END
DEFAULT
value=0
END
END
LAF array_split
STR_VAR
array=npc_class
match_key=is_annoying
RET_ARRAY
annoying_npcs=split
tolerable_npcs=rest
END
The annoying_npcs array will contain the Jan, Aerie and Anomen entries, the tolerable_npcs array will contain the rest. You can match values instead, or match both at once.
You can use the anonymous function construct with array_split: here's the same task as above via anonymous functions:
LAF array_split
STR_VAR
array=npc_class
match_key="! ~__~ STRING_MATCHES_REGEXP ~\(Anomen\|Jan\|Aerie\)~"
RET_ARRAY
annoying_npcs=split
tolerable_npcs=rest
END
This function checks only the first key in multi-key arrays.
The array_join function joins two arrays together, so that an entry is in the new array whenever it is in the old array. If there is a mismatch (the first and second array assign a different value to the same key(s)), the second array takes precedence.
For instance:
ACTION_CLEAR_ARRAY annoying_npcs
ACTION_CLEAR_ARRAY tolerable_npcs
ACTION_DEFINE_ASSOCIATIVE_ARRAY annoying_npcs BEGIN
Anomen=>1
Aerie=>1
Jan=>1
END
ACTION_DEFINE_ASSOCIATIVE_ARRAY tolerable_npcs BEGIN
Minsc=>1
Sarevok=>1
END
LAF array_join
STR_VAR
array1=annoying_npcs
array2=tolerable_npcs
RET_ARRAY all_npcs=array
END
The output array will have all five entries in it.
This just copies an array to a new array (something surprisingly hard to do, in full generality, in WEIDU).
LAF array_copy STR_VAR array=old_array RET_ARRAY new_array=array END
The array_invert function just swaps an array so that keys become values and vice versa. Note that if more than one key has the same value, array_invert will delete data. (Later entries in the array will take priority over earlier ones.)
For instance, if you apply array_invert to the 'annoying_npcs' array, defined above, like this:
LAF array_invert STR_VAR array=annoying_npcs RET_ARRAY annoying_npcs_inverted=array END
then the resultant array will contain only
1=>Jan
The array_sort function sorts an array by its keys. The sort rule is specified by an sfo-standard function which acts on the keys: its outputs are sorted lexicographically. (The sort function doesn't have to be one-to-one; if it isn't, the original order breaks ties.)
For instance, let is_annoying be the function defined in array_split, above, and consider this code:
ACTION_CLEAR_ARRAY all_npcs
ACTION_DEFINE_ASSOCIATIVE_ARRAY all_npcs BEGIN
Minsc=>1
Anomen=>1
Jan=>1
Aerie=>1
Sarevok=>1
END
LAF array_sort STR_VAR array=all_npcs function=is_annoying RET_ARRAY all_npcs=array END
The result is that the keys of all_npcs now appear in the order (Minsc,Sarevok,Anomen,Jan,Aerie). You can use the anonymous function construct.
The array_map function manipulates an array by applying a sfo standard function 'keymap' to its keys and/or 'map' to its values. (Either function can be absent, in which case no change is made.)
For instance:
ACTION_CLEAR_ARRAY npc_classes
ACTION_DEFINE_ASSOCIATIVE_ARRAY npc_class BEGIN
Minsc=>RANGER
Jaheira=>DRUID
Aerie=>CLERIC_MAGE
Edwin=>MAGE
Imoen=>MAGE_THIEF
END
DEFINE_PATCH_FUNCTION castertype STR_VAR arguments="" RET value BEGIN
PATCH_MATCH "%arguments%" WITH
CLERIC_MAGE BEGIN
SPRINT value "mixed"
END
".*MAGE.*" "BARD" "SORCERER" BEGIN
SPRINT value "arcane"
END
".*CLERIC.*" ".*DRUID.*" "RANGER" "PALADIN" "SHAMAN" BEGIN
SPRINT value "divine"
END
DEFAULT
SPRINT value "none"
END
END
LAF array_map
STR_VAR
array=npc_classes
map=castertype
RET_ARRAY
npc_castertypes=array
END
The outputted array will be
Minsc=>none
Jaheira=>divine
Aerie=>mixed
Edwin=>arcane
Imoen=>arcane
If you use 'keymap' instead, the function acts on the keys rather than the values. You can use the anonymous function construct.
Given an array, array_fill fills all entries in the array with some fixed entry. For instance:
LAF array_fill STR_VAR array=npc_array fill="-1" RET_ARRAY npc_array=array END
sets every entry value in npc_array to "-1".
array_read
The array_read function reads data from a file (or, when used as a patch function, from the current file) and puts it into an array. The file should either be a single column of entries (in which case each becomes a key, and the value of each key is "") or else two columns of entries (in which the first entry in each row is a key and the second is the value of that key). Any columns after the second are ignored.
For instance, here is code to read in the contents of race.ids into an array with keys equal to the numerical race identifiers and values equal to their human-readable versions, so that (e.g.) $race_array("107")="ETTERCAP":
COPY_EXISTING - race.ids nowhere
LPF array_read INT_VAR firstrow=1 RET_ARRAY race_array=array END
Here, firstrow is an optional argument telling the function which row to start at (counting up from zero) – in race.ids, the first row is 'IDS V1.0' and should be skipped.
By default, array_read reads arrays in in mixed case (i.e., the case that they’re actually stored in). If you set the STR_VAR 'case' to 'upper' or 'lower' you can force uppercase or lowercase. You can also specify the INT_VAR backwards=1 if you want to treat column 2 as keys and column 1 as values: here's code to read the races so that (e.g.) $race_array("ETTERCAP")=107:
COPY_EXISTING - race.ids nowhere
LPF array_read INT_VAR backwards=1 firstrow=1 RET_ARRAY race_array=array END
Here's the format for action context:
LAF array_read
STR_VAR
file="weapons.txt"
location="resource"
RET_ARRAY
array=weapprof_array
END
'File' is the file to be read in (here, some file in your mod detailing weapon data); you can specify its location via any/all of 'location', 'locbase', or 'path', as usual for SFO.
For instance, here's code to write the array 'npc_classes' to file:
There are two optional boolean (INT_VAR) arguments. If 'new' is set to 1, then any existing file of the same name is overwritten (if new=0, the default, the new values are instead appended). If 'permanent' is set to 1, any existing file is overwritten and the file will not be deleted when the mod component is uninstalled. (You should seldom if ever release a mod that uses this setting: it's for development, research, and testing.) Setting permanent=1 automatically sets new=1.
This function takes as input a string of key-value pairs in the format 'k=>v', separated by spaces, and turns it into an array of key-value pairs. You can use quotation marks if the key/value has spaces in. For instance,
LAF array_from_string
STR_VAR string="Minsc=>Awesome Amonen=>Annoying Sarevok=>~Treacherous, watch out~"
RET_ARRAY test_array=array
END
generates the 'test_array' array defined above in array_contains.
This function takes a list of keys, separated by spaces, and turns them into an array (with all values blank). For instance,
LAF array_keys_from_string
STR_VAR string="Minsc Anomen ~Sir Anomen~ Sarevok Aerie"
RET_ARRAY npc_array=array
END
generates this array:
Minsc=>""
Anomen=>""
"Sir Anomen"=>""
Sarevok=>""
Aerie=>""
If you want the string separated by something other than spaces, you can specify a different character, like this:
LAF array_keys_from_string
STR_VAR
string="Minsc,Anomen,Sir Anomen,Sarevok,Aerie"
separator=","
RET_ARRAY
npc_array=array
END
This generates the same array.
This is very similar to array_keys from string, but it generates an array with sequentially-numbered keys (starting at zero) and string entries as values. For instance,
LAF array_values_from_string
STR_VAR string="Minsc Anomen ~Sir Anomen~ Sarevok Aerie"
RET_ARRAY npc_array=array
END
generates this array:
0=>Minsc
1=>Anomen
2=>"Sir Anomen"
3=>Sarevok
4=>Aerie
This basically replicates the native WEIDU command ACTION_DEFINE_ARRAY, but it can be used with strings generated elsewhere. Again, you can use 'separator' to specify a string with entries separated by something other than spaces.