Introduction to Pluggy Arrays

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search

This article provides an introduction to arrays and their use via Pluggy. Those who are familiar with arrays may wish to skip ahead to the Overview for Programmers.

What is an Array?[edit | edit source]

Normal variables may only store a single value, but it's often useful to be able to store data in sets. Pluggy works with single dimension arrays, which you can think of as a sheet of lined paper: each line contains a seperate piece of information. Each line or piece of information is called an index, which is addressed by number. The first index in an array is always 0.

An example array containing 6 integer elements:

Index Value
0 1
1 5
2 16
3 9
4 31
5 28

Arrays in Pluggy[edit | edit source]

For a full list of the Pluggy functions which pertain to arrays, see Array Functions

Creating Arrays[edit | edit source]

Before an array can be used, it must be created by the CreateArray function, which returns the array's ArrayID. This ArrayID is an integer value, and should be stored in a long variable. Essentially, the ArrayID is the array's identifier within Pluggy - to access an array in any way, you must have its ArrayID.

Managing Arrays[edit | edit source]

Pluggy arrays vastly expand the tools available to a scripter, however, they also require some additional responsibility. When a Pluggy array is created, memory is set aside to contain the array. That memory will be freed up only when the scripter uses the function DestroyArray to indicate that they are finished with an array. Note also that undestroyed arrays "stick around" even after the game is closed - they are saved in .pluggy files, and will be loaded when the player loads a saved game. While this is excellent in terms of allowing us to save data, it also means that unused, undestroyed arrays will persist and continue to waste memory.

In order to avoid these problems, it's important that you:

  1. Be very careful when overwriting an existing ArrayID. Be sure that you've destroyed an array before overwriting its ArrayID - otherwise, you've got a memory leak. If possible, you can reuse the existing array (rather than destroying it and creating a new one) by setting its size to 0 with ArraySize.
  2. Be sure that each use of CreateArray (or CopyArray) is matched with a use of DestroyArray, except for the times when you specifically want an array to persist.

Data Types[edit | edit source]

Arrays within Pluggy are not restricted to any one variable type; they may contain any mix of Integers, Floats, or Refs, in addition to indexes which are empty. GetTypeInArray can be used to determine which type of variable is stored in a particular index.

Such flexibility allows you to store a large variety of information within a single array, rather than needing multiple arrays; you need only keep track of which index stores what information. For example, if you wanted to store information about an item, in this case a gold coin, you might want to use an array that contained:

Index Value Type Description
0 0000000F Reference Gold's FormID
1 319.53 Float Position (X)
2 20.30 Float Position (Y)
3 491.83 Float Position (Z)
4 1 Long Value

Dynamic Arrays[edit | edit source]

Pluggy arrays are dynamic, meaning that they can grow or shrink while the game is running. This is invaluable when you don't know ahead of time how much information you'll need to store, or when the information you're storing is constantly changing, e.g. tracking a list of items that the player has used.

  • ArraySize can be used to expand an array without actually setting the new indexes. When used to shrink an array, it will delete any indexes beyond the new size.
  • SetInArray, SetFloatInArray and SetRefInArray can take an optional argument (BlockSize) which allows them to expand an array to make room for new data.
  • RemInArray will clear the data at an index, leaving that index empty. You can then use PackArray to delete the empty index from the array, decreasing its size.

Protection and Ownership[edit | edit source]

Each array within Pluggy is "owned" by a particular Esp. Usually, this will be the Esp which created it. In addition, each array has a Protected flag. When set, only the Esp which owns the array will be able to modify it. By default, all arrays are not protected - unless you have a specific reason to leave your arrays open, you should always set them as protected, by using ArrayProtect or the Protected argument on CreateArray.

When to Use Arrays[edit | edit source]

  • When you need to store a large amount of information, needing a large number of variables. Arrays combined with OBSE's looping functions can allow you to address hundreds of variables with just a few lines of code, versus the hundreds of lines of code (and hundreds of variable declarations) that would be required otherwise.
  • When you need a data storage solution that can grow or shrink, rather than being static.
  • When you'd like to easily store a "set" of data, such as multiple pieces of information about an item, as shown in the Data Types Example.

Example[edit | edit source]

The following example could be used to store information about items in the player's inventory. It uses a pair of arrays to hold the information:

  • pInventory, which holds the ObjectID of the item.
  • pItemCount, which store the number of items that the player has.

These arrays simply use matching indexes to store information, meaning that if you find an item at index 5 in pInventory, you know that you can look at index 5 of pItemCount to find out how many of those items the player is carrying.

long pInventory
long pItemCount

long index

ref tItem
long tCount

...

set pInventory to CreateArray -1 0 1
set pItemCount to CreateArray -1 0 1

set index to 0

label
  set tItem to player.GetInventoryObject index
  set tCount to player.GetItemCount tItem
  
  SetRefInArray pInventory index tItem 1
  SetInArray pItemCount index tCount 1
  
  set index to index + 1
  if (index < player.GetNumItems)
    goto
  endif
  
;code that uses the stored information

DestroyArray pInventory
DestroyArray pItemCount

In order to see if the player had an item, the following code could be used:

set tItem to MyItem

set index to FindRefInArray pInventory tItem

if (index > -1)
  set tCount to GetInArray pItemCount index
  
  ;Player has MyItem, tCount now holds how many he has
  ;Do something with this info
else
  ;Player doesn't have MyItem
endif

Note[edit | edit source]

The above example is intended only as a demonstration of array usage, and is not recommended for actual use in a mod. If the player had any significant number of items in his inventory, the above code would be extremely taxing on the CPU, and likely would cause the game to appear to freeze for a second or two.

Overview for Programmers[edit | edit source]

  • ArrayIDs are much like pointers; you can pass them between scripts in order to access an array.
    • Also similar to pointers, arrays must be created and destroyed. Unless you specifically want to keep an array, each CreateArray or CopyArray should have a matching DestroyArray.
  • Pluggy arrays are dynamic:
    • ArraySize can be used to expand or shrink an array.
    • Use the BlockSize argument on the Set___InArray functions to expand an array to contain a new variable (much like std::vector.push_back() in C++).
    • RemInArray will clear the data at a specific index, after which PackArray can be used to remove the now empty index from the array.
  • Pluggy arrays can mix data types. Simply use the set function for the data type you wish to set:
    SetInArray (integers), SetFloatInArray and SetRefInArray.
    • Use GetTypeInArray to determine the data type stored at a particular index.
  • Pluggy only has no direct support for multidimensional arrays, but since ArrayIDs are simply integers, you can use an array to store the ArrayIDs of other arrays.