This wiki is a copy of the original Oblivion CS wiki created and maintained by the UESP.net. See CSwiki:Copy Notice for more info.

Introduction to Pluggy Arrays

From the Oblivion ConstructionSet Wiki
Revision as of 12:49, 26 March 2008 by imported>Speedo (→‎Example: Expanding example)
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?

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

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

Creating Arrays

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

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 should simply reuse the existing array rather than destroying it and creating a new one.
  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.

Protection and Ownership

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.

Data Types

Arrays within Pluggy are not restricted to any one 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

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. a list of items in the player's inventory.

  • 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.

When to Use Arrays

  • 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

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 using 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 the player had an item, the following code could be used:

set item to MyItem

set index to FindRefInArray pInventory item

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

Overview for Programmers

  • 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. See Multidimensional Pluggy Arrays.