Jump to content

Are Arrays Passed by Reference?


Haravikk

Recommended Posts

I just want to confirm, since it's not mentioned explicitly on any wiki that I've seen (or I've been looking in the wrong places or have gone crosseyed from looking) but are Arrays in Fallout 4's version of papyrus passed by value (copied) or by reference (any variable pointing at the same array can change it for all variables)?

 

I'm used to scripting in Skyrim where you could never really do much with arrays without re-creating them (and usually with PapyrusUtils since vanilla Skyrim at least didn't support expressions for array length) so I never really had much need to manipulate arrays I was given, as I'd just be creating a new one and returning it.

 

But in Fallout 4 we have dynamically sized arrays, along with methods like Array.Add(), Array.Insert() etc.

 

So I just wanted to confirm to make sure I haven't made a mistake, but am I correct in thinking that Arrays are passed by reference, so if I receive an array as an argument in a function and then add to it (using Array.Add or Array.Insert), the calling script will be able to access it? As a silly example (forgive typos):

Int Function CountEquipped(Actor akActor, Int[] aiIndices, Form[] akFound = None)
    Int aiCount = 0
    Int aiIndex = 0
    While aiIndex < aiIndices.Length
        WornItem akWorn = akActor.GetWornItem(aiIndices[aiIndex])
        If akWorn && akWorn.Item
            aiCount += 1
            If akFound
                akFound.Add(akWorn.Item)
            EndIf
        EndIf
        aiIndex += 1
    EndWhile
    Return aiCount
EndFunction
    {Counts the number of equipped items on akActor found in slots listed in aiIndices, optionally adding each found item to akFound}

Basically I just want to confirm that a function such as the above (which puts found items into akFound) should work, or if I need to find a way to convert them to return multiple values as a Var[] array or similar?

Link to comment
Share on other sites

Unfortunately they are passed by copy. Moreover and potentially even worse, they "new" keyword indicates they are created on the heap. And if this is the case, the only way to get that memory back, partially, is to clear(), or to let the game rebuild the heap. Simply exiting function- or script scope will not destroy the array. But it will terminate your access to it!

Link to comment
Share on other sites

Simply exiting function- or script scope will not destroy the array.

 

 

I don't think that's true. Unless you use the compiler patch for structs in arrays and make complicated data structures with circular references, garbage collection will take care of it.

Link to comment
Share on other sites

Function level variables or arrays will be cleaned up after the function exits.

 

Script level variables or arrays should be cleaned up if/when the script clears EXCEPT non CONST scripts that can hold script level variables or arrays do not seem to clean up consistently (hanging scripts). Which is why attaching non CONST scripts to short lifecycle objects is bad. Therefore manually clearing script level properties, variables and arrays when they are done is a pro tip ya dont see that often.

Link to comment
Share on other sites

Arrays defenitely passed by reference to a function. In other case my mod will never works.

 

In my mod array object is created and passed to external function for modification.

After external function finish caller uses changes made by external function.

Edited by DlinnyLag
Link to comment
Share on other sites

Basically I just want to confirm that a function such as the above (which puts found items into akFound) should work, or if I need to find a way to convert them to return multiple values as a Var[] array or similar?

If I understand your problem correctly then yes, elements added to akFound will be visible on the caller side.

But in this particual case you could return newly created array instead of passing.

Somethig like that:

Form[] Function GetEquipped(Actor akActor, Int[] aiIndices)
    Form[] retVal = new Form[0]
    Int aiIndex = 0
    While aiIndex < aiIndices.Length
        WornItem akWorn = akActor.GetWornItem(aiIndices[aiIndex])
        If akWorn && akWorn.Item
            retVal.Add(akWorn.Item)
        EndIf
        aiIndex += 1
    EndWhile
    Return retVal
EndFunction

The length of retuned array will be equal to your aiCount

Edited by DlinnyLag
Link to comment
Share on other sites

 

I just want to confirm, since it's not mentioned explicitly on any wiki that I've seen (or I've been looking in the wrong places or have gone crosseyed from looking)

Please see Assigning/Passing Arrays section at https://www.creationkit.com/fallout4/index.php?title=Arrays_(Papyrus)

 

Must have missed that somehow! However it only specifically shows setting an existing index (Array1[0] = 10), does the same rule hold true when using Array1.Add(10)? My actual case is proving complex to debug, I really need to add some very basic scripts just to test what behaviours might be broken (or misunderstood in my case), been a busy week though, I'll see if I can find time over the weekend.

 

 

Basically I just want to confirm that a function such as the above (which puts found items into akFound) should work, or if I need to find a way to convert them to return multiple values as a Var[] array or similar?

If I understand your problem correctly then yes, elements added to akFound will be visible on the caller side.

But in this particual case you could return newly created array instead of passing.

 

I should have said but the example was very much simplified compared to what I'm actually doing (to try and give a clearer idea of my question); in my actual case I have multiple arrays that I need to add entries to, ideally without having to return them somehow, so arguments will be the best way if that does in fact work.

 

You're right that that specific example could just return the array, though my intention was that filling the array at all in the example is optional (no array needs to be passed if all you need is the total), also the array being passed in might not be empty (it may be passed between functions, each adding their own entries), which is part of what I'm actually doing (multiple functions adding their data to a set of arrays), at least, what my scripts are supposed to be doing.

Edited by Haravikk
Link to comment
Share on other sites

though my intention was that filling the array at all in the example is optional (no array needs to be passed if all you need is the total), also the array being passed in might not be empty (it may be passed between functions, each adding their own entries), which is part of what I'm actually doing (multiple functions adding their data to a set of arrays), at least, what my scripts are supposed to be doing.

 

You can use F4DS if you have worries about built-in arrays functionality and F4SE usage is acceptable.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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