String Variables

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search


A variable type added by Oblivion Script Extender (OBSE).


OBSE v0016 introduces the string_var datatype for representing strings of characters.


String variables can be declared and used like normal variables and can hold the return values from OBSE commands defined as returning a string_var. Their contents are preserved with the savegame.


String-related commands include commands to modify a string variable and commands to retrieve a game string and store it in a string variable. Additionally, many existing commands like SetName now have EX counterparts (i.e. SetNameEX) which can accept a format string and a variable number of arguments, including string variables.


A string variable should not be used until it has been initialized with a value, by using it on the left hand side of a call to sv_Construct or a command that returns a string.


An uninitialized string variable has a value of zero, which can be tested for in scripts. The value of an initialized string, on the other hand, is undefined and should never be modified directly by statements such as set someStringVar to 6 or using arithmetic operators.


Similarly, string variables should only be used to store strings, and the result of a string-returning variable should only (and always) be assigned to a string variable.


Creating and using string variables[edit | edit source]

Strings are created when you assign a string to a variable of type 'string_var'.

string_var string1

Let string1 = "Hello World"  


String variables, actually, hold an internal ID of the string. The string itself is stored somewhere else in memory and is internally connected to the ID stored in the string_var. Understanding this structure may help in some situations.


Using LET to assign a string to a non-initialized string_var creates a new string in memory

  Let string1 := “Hello”
     • string1 points to a newly created  “Hello” string

Using LET to assign a string to an initialized string_var replaces the original string with the new string

  Let string1 := “World”
     • Destroys the original “Hello” string
     • Creates a “World” string
     • string1 points to the “World” string

Using LET to assign a String_var to another string_var creates a new copy of the string

  Let string2 := string1
     • Creates a new “World” string
     • string2 points to the newly created  “World” string
     • string1 still points to the same “World” string as before
     • string1 and string2 may be changed without affecting each other (as they are different strings)

Concatenating strings[edit | edit source]

Strings may be concatenated using the '+' operator.

You may use any combination of string_vars and literals

Let string1 = "Hello"
Let string2 = "World"  

let string3 = string1 + " Wide " + string2


Using string vars in place of literals[edit | edit source]

String variables can be passed to any command expecting a string literal as an argument by prefacing the name of the variable with a dollar sign.

The variable can be a quest variable, specified as $quest.varname, or local to the calling script specified as $varname. Example:

string_var msg

let msg := "Greetings from Stonekeep, " + player.GetName + "!!!"

MessageBox $msg


This deprecates many of the Set...EX commands.

Additionally in v0017, support for string operations has been integrated into the language via OBSE expressions, which leaves functions such as sv_Construct, sv_Substring, etc. mostly deprecated.


Warning: using SET with string_vars[edit | edit source]

Using SET to assign a String_var to another string_var copies the ID from one var to the other causing both variables to refer to the same string. For instance, in the following code:

string_var string1
string_var string2

set string1 to sv_Construct "First string"
set string2 to string1	
set string1 to sv_Construct "Second string" ; modifies both string1 and string2

both string1 and string2 end up containing "Second string." If this is not desired behavior, use LET to copy the contents of one string to another.

The problem is that SET was developed before strings were implemented, so it does not handle them well, so it is not prepared to destroy the previous string pointed by the string2.

Like in this example:

  Let string1 := “Hello”
  Let string2 := “World”
  Set string2 to string1
     • DOES NOT destroy the original “World” string originally pointed by string2 >> BLOAT

That “World” will stay in the savegame, unused and unreachable, until the mod is removed.

So, if you need to have two variables pointing to the same string, make sure you explicitly destroy the original string before assigning a new string with LET, like this:

  Let string1 := “Hello”
  Let string2 := “World”
  sv_destruct string2
  Set string2 to string1

Destroying string variables[edit | edit source]

String variables persist in the savegame until they are explicitly destroyed or until the mod from which they originate is removed from the user's mod list.

In general, string variables should be destroyed after use unless it is necessary to save their values permanently.

In the following example, the string variable is used each time the scripted object is activated:

string_var refName
ref activatingRef

begin onActivate

  set activatingRef to GetActionRef
  set refName to activatingRef.GetName

  if (sv_Count "e" refName > 0)
    Message "Your name contains the letter e"
  endif

  set refName to sv_Destruct

end

Because the value of the string variable is only needed temporarily, sv_Destruct is used to prevent it from being saved.


A string stored in a string_var will be destroyed when another string is assigned to that string_var.

Int n
String_var MyString

. . .
Let n += 1
If n == 1
  Let MyString := “This is a very very very very very very very very very very long string”

Elseif n = 1000
  Let MyString := “This is a short string”

Elseif n = 2000
  Sv_destruct MyString

endif

In the above example the long string will exist for 1000 frames (or 1000 runs of the script) and will be in the savegame if the game is saved during this period, but will be destroyed when the short string replaces it in the string var.

The short string will exist for another 1000 frames (and will be in the savegame if the game is saved during this period) and will, then, be destroyed by the sv_Destruct.

So, to prevent those strings taking space in savegames it is good practice to destroy them as soon as possible.


Strings stored in arrays[edit | edit source]

A string stored in an array (which is not a string_var) will always be destroyed when there are no references remaining to that array.

Array_var MyArray

. . .
Let MyArray := ar_construct array

Ar_append MyArray “This is a string”

Let MyArray := GetUserTime

In this example, the string “This is a string” will be destroyed when the original array is replaced by the array returned by GetUserTime.


Strings in user functions[edit | edit source]

A string stored in a string_var declared in a User Defined Function:

  • Will be automatically destroyed if it is used to store an argument
  • Otherwise it will not be automatically destroyed


Scn MyFunction
String_var s1
String_var s2
String_var s3
 
Begin Function {s1}

  Let s2 := “aaaaa”

  Let s3 := “bbbbb”

  Sv_destruct s2

End

In this example:

  • S1 will be automatically destroyed at the end of the function
  • S2 will be explicitly destroyed by sv_destruct
  • S3 will not be destroyed and will bloat the savegame with “bbbbb”s every time the function is called