Difference between revisions of "Array Reference"

From the CreationKit Wiki
Jump to navigation Jump to search
imported>Jlundin
 
m (→‎Large Arrays without SKSE: Reverted accidental edit of heading level)
 
(6 intermediate revisions by 3 users not shown)
Line 16: Line 16:
MyObject[]
MyObject[]
</source>
</source>
 
<br>
== Array Creation ==
== Array Creation ==
  <array creation> ::= 'new' <element type> '[' <int> ']'
  <array creation> ::= 'new' <element type> '[' <int> ']'


To create an array, use the "new" keyword, followed by the type and size. The Size is denoted by the integer between the two square brackets, and cannot be a variable. (In other words, array size must be defined at compile time)  
To create an array, use the "new" keyword, followed by the type and size. The Size is denoted by the integer between the two square brackets, which must be between 1 and 128. Also, it cannot be a variable. (In other words, array size must be defined at compile time)  


The initial value of each element will be the [[Default Value Reference|default value]] for the type.
The initial value of each element will be the [[Default Value Reference|default value]] for the type.
Line 38: Line 38:
MyScript[] x = new MyScript[5]
MyScript[] x = new MyScript[5]
</source>
</source>
 
<br>
== Array Length ==
== Array Length ==
  <array length> ::= <expression> '.' 'Length'
  <array length> ::= <expression> '.' 'Length'
Line 56: Line 56:
x = myArray.Length ; x will get 0
x = myArray.Length ; x will get 0
</source>
</source>
 
<br>
== Array Elements ==
== Array Elements ==
  <array access> ::= <expression> '[' <expression> ']'
  <array access> ::= <expression> '[' <expression> ']'


To get a specific array element, just put the index of the element you want between two square brackets. This value can also come from an [[Expression Reference|expression]], or a return value of a [[Function Reference|function]], or something else. The valid elements in an array are from 0 to the length minus 1.
To get a specific array element, just put the index of the element you want between two square brackets. This value can also come from an [[Expression Reference|expression]], or a return value of a [[Function Reference|function]], or something else (see Warnings below for an exception). The valid elements in an array are from 0 to the length minus 1.


=== Examples ===
=== Examples ===
Line 72: Line 72:
x = myArray[myArray.Length - 1]
x = myArray[myArray.Length - 1]
</source>
</source>
<br>
== Warnings ==
*Only the = assignment operator can be used with an [[Arrays_(Papyrus)|array]] (see [[Operator_Reference#Assignment_Operators|Assignment Operators]]):
<source lang="papyrus">
; Will not compile, as the compiler doesn't know how to handle it.
myArray[3] += 5
</source>
<br>
=== Compiler Issues ===
Several compiler errors have been identified that are caused by using expressions inside of array index brackets. The standard papyrus compiler sometimes compiles expressions inside of array index brackets incorrectly, leading to unexpected behavior and data corruption. As a result, it is recommended to avoid using complex expressions or function calls inside of array index brackets when possible. '''[http://forums.bethsoft.com/topic/1491368-weird-array-index-behavior/ See this discussion]''' for further details and analysis of the problems outlined below:
<br>
*Using complex expressions inside of the index brackets of an integer array can cause unexpected behavior -
<source lang="papyrus">
;these work fine:
myIntArray[i] = newValue
myIntArray[i * 5] = newValue
;this will result in unexpected values being inserted into the array at run time:
myIntArray[i * 5 + 1] = newValue
</source>
<br>
*The array Find() function should not be used within an array's index brackets; it can also cause unexpected results -
<source lang="papyrus">
;this works fine:
i = myArray.Find(none)  ;(find the first blank element)
myArray[i] = newValue  ;(and fill it with our newValue)


;this will result in values being inserted into unpredictable indices of the array at run time:
myArray[myArray.Find(none)] = newValue
</source>
<br>
== Advanced Usage ==
=== SKSE ===
You can create Arrays larger than 128 elements and variable in size using the helper functions in the [[Utility_Script#SKSE_Global_Functions|Utility script]].
<source lang="papyrus">
float[] LongArrayOfFloats = Utility.CreateFloatArray(512)
int i = 2048
string[] VariableSizeArrayOfStrings = Utility.CreateStringArray(i)
</source>
You can access it like any other array.
<source lang="papyrus">
Debug.trace(LongArrayOfFloats[250])
</source>
SKSE also allows you to resize any array on the fly:
<source lang="papyrus">
Utility.ResizeStringArray(VariableSizeArrayOfStrings, 64)
</source>
=== Large Arrays without SKSE ===
If an array larger than 128 elements is required, a work-around is to use multiple arrays to form one large array. Below is an example of how this can be accomplished for an array that can hold 512 floats:
<source lang="papyrus">
float[] Array1
float[] Array2
float[] Array3
float[] Array4
function CreateArray()
{ Use to create the array. }
    Array1 = new float[128]
    Array2 = new float[128]
    Array3 = new float[128]
    Array4 = new float[128]
endFunction
float function GetArrayElement(int index)
{ Use to get the value of the array element at the given index (between 0 and 511). }
    if (index < 128)
        return Array1[index]
    elseIf (index < 256)
        return Array2[index - 128]
    elseIf (index < 384)
        return Array3[index - 256]
    elseIf (index < 512)
        return Array4[index - 384]
    else
        Debug.Trace("Error: Array index " + index + " exceeds the maximum of 511.", 2) ; Error.
    endIf
endFunction
function SetArrayElement(int index, float value)
{ Use to set the value of the array element at the given index (between 0 and 511). }
    if (index < 128)
        Array1[index] = value
    elseIf (index < 256)
        Array2[index - 128] = value
    elseIf (index < 384)
        Array3[index - 256] = value
    elseIf (index < 512)
        Array4[index - 384] = value
    else
        Debug.Trace("Error: Array index " + index + " exceeds the maximum of 511.", 2) ; Error.
    endIf
endFunction
</source>
<br>
[[Category:Scripting]]
[[Category:Scripting]]
[[Category:Papyrus]]
[[Category:Papyrus]]
[[Category:Papyrus Language Reference]]
[[Category:Papyrus Language Reference]]

Latest revision as of 07:30, 23 June 2023

Arrays are values that contain several other values, indexed by a 0-based number. (0 is the first element, 1 in the second, and so on).

Array Type[edit | edit source]

<array type> ::= <element type> '[' ']'

An array type is denoted by adding a pair of empty brackets after the type of the elements. The element type may only be a non-array type, so multi-dimentional arrays are not allowed. These types can be used anywhere else other types are used - as parameter, return, variable, and property types.

Examples[edit | edit source]

; An array of integers
int[]


; An array of MyObjects
MyObject[]


Array Creation[edit | edit source]

<array creation> ::= 'new' <element type> '[' <int> ']'

To create an array, use the "new" keyword, followed by the type and size. The Size is denoted by the integer between the two square brackets, which must be between 1 and 128. Also, it cannot be a variable. (In other words, array size must be defined at compile time)

The initial value of each element will be the default value for the type.

If you make an array property, then the Creation Kit will determine the size of the array by how many elements are put into it.

Note that this cannot appear in the script outside of a function.

Examples[edit | edit source]

; Create an array of 20 floats
float[] x = new float[20]


; Create an array of 5 MyScripts
MyScript[] x = new MyScript[5]


Array Length[edit | edit source]

<array length> ::= <expression> '.' 'Length'

To get the length of an array, you can access the read-only length property on the variable holding the array. If the variable is None, the length will still succeed, but return 0. Note that the last valid index in an array is the length of the array, minus 1.

Examples[edit | edit source]

; Get the length of our array
int[] myArray = new int[10]
x = myArray.Length ; x will get 10


; Get the length of an uninitialized array (None)
float[] myArray
x = myArray.Length ; x will get 0


Array Elements[edit | edit source]

<array access> ::= <expression> '[' <expression> ']'

To get a specific array element, just put the index of the element you want between two square brackets. This value can also come from an expression, or a return value of a function, or something else (see Warnings below for an exception). The valid elements in an array are from 0 to the length minus 1.

Examples[edit | edit source]

; get the first element in the array
x = myArray[0]


; get the last element of the array
x = myArray[myArray.Length - 1]


Warnings[edit | edit source]

 ; Will not compile, as the compiler doesn't know how to handle it.
 myArray[3] += 5


Compiler Issues[edit | edit source]

Several compiler errors have been identified that are caused by using expressions inside of array index brackets. The standard papyrus compiler sometimes compiles expressions inside of array index brackets incorrectly, leading to unexpected behavior and data corruption. As a result, it is recommended to avoid using complex expressions or function calls inside of array index brackets when possible. See this discussion for further details and analysis of the problems outlined below:


  • Using complex expressions inside of the index brackets of an integer array can cause unexpected behavior -
;these work fine:
myIntArray[i] = newValue
myIntArray[i * 5] = newValue

;this will result in unexpected values being inserted into the array at run time:
myIntArray[i * 5 + 1] = newValue


  • The array Find() function should not be used within an array's index brackets; it can also cause unexpected results -
;this works fine:
i = myArray.Find(none)  ;(find the first blank element)
myArray[i] = newValue   ;(and fill it with our newValue)

;this will result in values being inserted into unpredictable indices of the array at run time:
myArray[myArray.Find(none)] = newValue


Advanced Usage[edit | edit source]

SKSE[edit | edit source]

You can create Arrays larger than 128 elements and variable in size using the helper functions in the Utility script.

float[] LongArrayOfFloats = Utility.CreateFloatArray(512)
int i = 2048
string[] VariableSizeArrayOfStrings = Utility.CreateStringArray(i)

You can access it like any other array.

Debug.trace(LongArrayOfFloats[250])

SKSE also allows you to resize any array on the fly:

Utility.ResizeStringArray(VariableSizeArrayOfStrings, 64)

Large Arrays without SKSE[edit | edit source]

If an array larger than 128 elements is required, a work-around is to use multiple arrays to form one large array. Below is an example of how this can be accomplished for an array that can hold 512 floats:

float[] Array1
float[] Array2
float[] Array3
float[] Array4

function CreateArray()
{ Use to create the array. }
    Array1 = new float[128]
    Array2 = new float[128]
    Array3 = new float[128]
    Array4 = new float[128]
endFunction

float function GetArrayElement(int index)
{ Use to get the value of the array element at the given index (between 0 and 511). }
    if (index < 128)
        return Array1[index]
    elseIf (index < 256)
        return Array2[index - 128]
    elseIf (index < 384)
        return Array3[index - 256]
    elseIf (index < 512)
        return Array4[index - 384]
    else
        Debug.Trace("Error: Array index " + index + " exceeds the maximum of 511.", 2) ; Error.
    endIf
endFunction

function SetArrayElement(int index, float value)
{ Use to set the value of the array element at the given index (between 0 and 511). }
    if (index < 128)
        Array1[index] = value
    elseIf (index < 256)
        Array2[index - 128] = value
    elseIf (index < 384)
        Array3[index - 256] = value
    elseIf (index < 512)
        Array4[index - 384] = value
    else
        Debug.Trace("Error: Array index " + index + " exceeds the maximum of 511.", 2) ; Error.
    endIf
endFunction