Jump to content

Arrays in Questscripts?


Recommended Posts

I would die for an example from you with nested arrays. :smile:

I did nested arrays for a project I'm working. Its kinda weird and silly how I accomplished it however

 

 

  ; initialize needed arrays
  let aArmor := ar_Construct Array ; array of arrays
  let aArmCurr := ar_Construct Array ; working array
  let iArmNum := 0   ; the number of nested arrays
  ; load up nested arrays, and increment a value of the number of nested arrays
  let aRichArm := ar_Construct Array
  let aRichArm[0] := UpperPants06	; Blue Silks
  let aRichArm[1] := UpperShirt06	; Blue Silk Shirt
  let aRichArm[2] := UpperShoes03	; Blue Suede Shoes
  let aRichArm[3] := JewelryRing6Ebony6Diamond	; Ebony Diamond Ring
  let aRichArm[4] := JewelryAmulet6Jeweled	; Jeweled Amulet
  let iArmNum += 1
  ....
  ; more arrays, you get the idea

  ; fill the array with your arrays
  let iIndex := 0
  While ( iIndex < iArmNum )
    let aArmor[iIndex] := aRichArm
    let iIndex += 1 
    ....
  Loop

  ; pass a nested array to a working array
  let iArmorSize := ar_Size aArmor	; returns numeric size
  ; we pass the random array we want to a temp array
  ; for some reason this effectively turns the NOTE, not sure what i meant here
  ; basically you're using the passed array like a normal array
  ; I'm getting a random number based on the size of the working array for my own needs
  let aArmCurr := aArmor[Rand 0 iArmorSize]
  let iArmCurrSize := ar_Size aArmCurr

  ; work on the passed array
  ; yes i used a while loop don't judge me 
  let iIndex := 0  ; set our index to 0 to walk through any array
  While (iIndex < iArmCurrSize)
    let rTemp := aArmCurr[iIndex]  ; assign a temp ref to the current array value
    PlayerREF.AddItemNS rTemp 1	; add said value to player
    PlayerREF.EquipItemNS rTemp	; equip said value on player

    let iIndex += 1
  Loop
  ....

Let me know if you have any questions

 

Link to comment
Share on other sites


Just expanding a bit on KatsAwful's example to demonstrate a 3-level nesting:


Suppose you have a number of NPCs, and you want to change their outfit according to some criteria, for example, one set of clothes for the mornings one for the afternoons and one for the evenings.



;--- Main array
array_var MyNPCs
let MyNPCs := ar_Construct stringmap


;--- Create an entry for the first NPC (John) and make this entry a nested stringmap array
let MyNPCs["John"] := ar_Construct stringmap


;--- Create an entry for the morning clothes and make this entry a nested standard array
let MyNPCs["John"]["Morning"] := ar_Construct array

;--- Add the morning outfit components (using KatsAwful's items)
;--- NOTE: I prefer ar_append over hard indexing ([0], [1], ...)
ar_Append MyNPCs["John"]["Morning"] UpperPants06 ; Blue Silks
ar_Append MyNPCs["John"]["Morning"] UpperShirt06 ; Blue Silk Shirt
ar_Append MyNPCs["John"]["Morning"] UpperShoes03 ; Blue Suede Shoes
ar_Append MyNPCs["John"]["Morning"] JewelryRing6Ebony6Diamond ; Ebony Diamond Ring
ar_Append MyNPCs["John"]["Morning"] JewelryAmulet6Jeweled ; Jeweled Amulet

;--- Create an entry for the afternoon clothes and make this entry a standard array
let MyNPCs["John"]["Afternoon"] := ar_Construct array


;--- Add the afternoon outfit components
ar_Append MyNPCs["John"]["Afternoon"] <whatever>
...
...

;--- Create an entry for the evening clothes and make this entry a standard array
let MyNPCs["John"]["Evening"] := ar_Construct array


;--- Add the evening outfit components
ar_Append MyNPCs["John"]["Evening"] <whatever>
...


;--- Create an entry for the second NPC (Mary) and make this entry a nested stringmap array
let MyNPCs["Mary"] := ar_Construct stringmap


;--- Create an entry for the morning clothes and make this entry a standard array
let MyNPCs["Mary"]["Morning"] := ar_Construct array


; etc, etc, etc ...



;--- An additional array to de able to find NPCs references
array_var MyNPCreferences
let MyNPCreferences := ar_Construct stringmap
MyNPCreferences["John"] := <reference to the John NPC>
MyNPCreferences["Mary"] := <reference to the Mary NPC>
...



Then, when the clock hits twelve noon, you can do something like this:



ForEach item <- MyNPCs
Let NPCname = item["key"]
Let NPCref := MyNPCreferences[NPCname];


;--- Remove morning items
ForEach item2 <- MyNPCs[NPCname]["Morning"]
NPCref.UnEquipItem item2["value"]
NPCref.RemoveItem item2["value"] 1
Loop


;--- Att afternoon items
ForEach item2 <- MyNPCs[NPCname]["Afternoon"]
NPCref.AddItem item2["value"] 1
NPCref.EquipItem item2["value"]
Loop

Loop



DISCLAIMER: My scripting is very rusty and I may have made a number of mistakes, but you should have the general idea.




Link to comment
Share on other sites

Well I do nest both arrays and have scripts pointing at each others, nesting, which makes it even impossible to compile them in the first place... ;) So how to compile them? By remarking the nests and pointers, compile them, remove the remarks and recompile. Then we have nice pointing and pointers here, there and everywhere but never no where. Is it possible to point no where or to the void? Yes, in C it is but not in Oblivion scripting as far as I know. Sometimes it is needed, to get stuff directed to the void...

Link to comment
Share on other sites

Well I do nest both arrays and have scripts pointing at each others, nesting, which makes it even impossible to compile them in the first place... :wink: So how to compile them? By remarking the nests and pointers, compile them, remove the remarks and recompile. Then we have nice pointing and pointers here, there and everywhere but never no where. Is it possible to point no where or to the void? Yes, in C it is but not in Oblivion scripting as far as I know. Sometimes it is needed, to get stuff directed to the void...

As far as I know setting a "ref" variable to "0" or better yet an "array_var" to "ar_Null" (and there's something with "string_var", too) does exactly that. But that's only in certain specific contexts. Other than those there are no pointers that I know of in ObScript/OBSE.

Link to comment
Share on other sites

(and there's something with "string_var", too)

sv_destruct str1, str2, str3, str4, ...

Can destroy up to 10 string variables at once.

 

I previously used it like that

Let str1 := sv_destruct

which is actually a dumb way to use it. ^^

 

 

It's recommended to use these to clear Arrays Vars (Let arrayVar := ar_Null) or String Vars, when no longer in use, otherwise it will result in savegame bloating.

 

 

 

 

@QQuix

Thank you sooooo much! :D

I might try and get nested arrays working now.

Nothing gets over a good example. :smile:

 

@KatsAwfuk

Thanks for your example too. Every bit of code helps to dig in. :wink:

Link to comment
Share on other sites

Keep in mind that OBSE keeps track of the number of references to each array and destroys the array when no references to it remain. This makes it unnecessary for scripts to worry about destroying arrays explicitly.

 

If you choose to destroy it yourself, make sure you use "Let arrayVar := ar_Null". This way, OBSE will do both: set the variable to 0 AND destroy the array, including nested arrays (if also not referenced elsewhere) . This does not happen if you use "Set arrayVar to 0". Not sure about "Let arrayVar := 0"

 

Btw, this automatic cleanup is not true for String_vars, which should be explicit destroyed, specially in User Functions.

Link to comment
Share on other sites

The word pointer can be used in different context Drake. In my case, it is when I call a function, or set a variable from on script to another - They point at eachothers. It might not be the right word so if you have to find a proper word for it, one sinlge word, which word would you have chosen?

Link to comment
Share on other sites

Another thing I forgot about nested arrays, OBSE seemingly doesn't like the syntax QQuix mentioned for pure indexed arrays.

arrayVar[indexA][indexB]

I didn't get complaints when compiling but for some reason the array would never be processed, unless I did something wrong. That's why I ended up doing the method I did

Edited by KatsAwful
Link to comment
Share on other sites

I am pretty sure that is the correct syntax, but I do not trust my memory that much and I may be misguided by working too close to C++ and too far from Obscripting for the last several years.

 

Some input from experienced scripters would be welcome.

Link to comment
Share on other sites

That is the correct syntax, yes. What exact runtime situation does lead to the error you receive? You aren't trying to skip indexes or start with numbers other than "0"?

 

Oh, but there's one more thing that should be taken care of:

For every "indexA" you'll also have to call "let arrayVar[indexA] := ar_Construct Array" as well at one point to initiate.

 

You cannot simply go like in PHP or C et al and decide about the array's dimensions just by setting another index, nor can you declare it as a 2- or N-dimensional array right from the start. Every dimension has to be specifically initialized as another array for every index.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...