Tutorial: Array Variables 1
Array variables refer to arrays. Arrays are lists of items - imagine them as 2-column tables that you'd use in Word or some such. See for instance these examples given on the Oblivion wiki.
Arrays are kept by NVSE for you, and whichever ones exist when a savegame is made will be stored in the .nvse file that corresponds to your save. They're the same as string vars that way.
Unlike with string vars, NVSE automatically cleans up redundant array variables when they are no longer referenced by an active script or another array. Array variables, like other types, will exist permanently if stored in a quest, but otherwise (Object, Spell and UDF scripts) are deleted when a script ends.
Types of Arrays, Keys and Values
There are different types of arrays we can use. The first, which we'll call a 'regular' array (array-type array, 'array' array and list array are also used) look and function a lot like vanilla formlists:
Example form list: NonAlcholicDrinks: 0 MS05NukaColaQstm 1 MS05IceNukaCola 2 NukaCola 3 WaterUnpurified 4 WaterPurified
Like formlists, regular arrays are indexed by positive consecutive integer numbers running from 0 to (Total Size - 1). Those index numbers are called keys.
The main difference, and the main advantage that all array types have, is that what's associated with those keys - the values - can be anything: not just forms and refs, but also numbers, strings and even other arrays. (When we talk about a key-value combination, we use the term "element".)
Example Regular Array: SomeArray: 0 NukaCola ; form 1 3 ; number 2 "You can't beat the real thing" ; string 3 RecipesInvolvingNukaColaArray ; array
As with formlists, the indexes will always be consecutive; if you remove any element, the others with a higher index will move up - index gaps are not allowed, and neither are floats or negative numbers.
This is a limitation sometimes, so for a different kind of numbered indexing, we have maps, which are arrays that can take any number as key, and allow for gaps (they have to because they allow decimals). So we can convert the "agenda" example from the CS wiki to this map, with the time converted to decimal and the activities held in strings:
Example Map: 8.5 "Sign in, coffee" 9 "Introduction" 9.5 "Presentation A" 10.5 "Coffee break" 11 "Presentation B" ; Note: arrays don't store the quotation marks, I just put them there to remind you they're strings
Here's another one that stores some exterior cells as values with their X coordinates as keys, some of them are negative:
Another Map: -21 MojaveOutpost -9 MojaveDriveIn 7 188TradingPost 12 BoulderCity 17 BitterSprings
Finally, sometimes numbers of whichever kind just don't cut it, so we have stringmaps, which take strings as keys:
Example StringMap: "Name" "Prudencia" "Age" 27 "Body" "T6M" "Profession" "Test character" "Time played (hrs)" 106.5 "Cells visited" CellsVisitedArray
Declaring and Initializing Arrays
You declare an array var of any type, just like any other variable:
array_var SomeArrayVarName int SomeIntName ref SomeRefName
And just like string vars, you can't do anything with them until they're initialized and refer to an actual array in NVSE. You may initialize arrays by either:
- Explicitly constructing them, by letting them to the Ar_Construct function, with the array type as parameter, if you want a new empty array:
let somearrayvarname := ar_construct array let somearrayvarname := ar_construct map let somearrayvarname := ar_construct stringmap
The type 'array', 'map' and 'stringmap' are string parameters to the Ar_Construct function, just like 'Health' is to GetAV in GetAV Health. Especially if you toggle the Script Compiler Override on, you will see a warning about such strings, in which GeckPU will basically say 'I'm assuming these are strings but you can still change your mind so I'm not compiling yet'. If you ignore that warning and compile anyway, things will work fine in-game. Or you can enclose them in "" speech marks to prevent the warning.
- By letting them to another array var, which makes both array vars refer to the same array:
let somearrayvar2 := somearrayvar1 let somearrayvar1[2] := something ; --> somearrayvar2 now also has the new element, because it's the same array
If 2 array vars refer to the same array like that, you can break one free by ar_constructing it, which makes it point to a new, empty array:
let somearrayvar2 := ar_construct array --> somearrayvar2 now refers to brand new, empty array
If you want to genuinely duplicate an array, use Ar_Copy or Ar_DeepCopy.
- Or, by letting them to the result of any function that returns an array (including UDFs that return an array with SetFunctionValue). There are many such functions available, such as Ar_List, Ar_Map, Ar_Range, Ar_Copy, etc.
array_var Beatles array_var MagicNumberToString array_var StringToMagicNumber let Beatles := Ar_List JohnREF, PaulREF, GeorgeREF, RingoREF ; * new regular array let MagicNumberToStrong := Ar_Map 2::"Upper body", 5::"Weapon", 10::"Hat" ; * new map let StringToMagicNumber := Ar_Map "Upper body"::2, "Weapon"::5, "Hat"::10 ; * new stringmap
You can also uninitialize an array var by letting it to Ar_Null:
let somearrayvar := ar_Null
From that point on it's pretty much like a null ref var. If you want to know if an array is initialized or not before you try and do something with it, you can just check it as a bool, or use LogicalNot (!) to check its being uninitialized:
if somearrayvar ; arrayvar is initialized else ; uninitialized endif if eval !(somearrayvar) ; array var is not initialized endif
If you already know it's initialized, there's no point.
Part 2: Retrieving and Storing Elements