lee3310 Posted February 7, 2023 Posted February 7, 2023 (edited) Here's what i'm trying to do: Struct aStruct Actor akActor Int akActorValue EndStruct aStruct[] Property ArrayOfStructs auto Function MyFunction() aStruct MyStruct = new aStruct MyStruct.akActor = anActor MyStruct.akActorValue = anActorValue ArrayOfStructs.add(MyStruct) EndFunction In the log i get this: "error: Cannot add elements to a None array" I can properly fill the Struct property in the editor and when i click "add", a new window with "Actor" and "Int" vars opens so i can assume that the property is indeed an array but i want to fill it in the script. Edited February 7, 2023 by lee3310
RaidersClamoring Posted February 7, 2023 Posted February 7, 2023 A 'single' (jargon) Auto property needs to be populated or at least initialized in CK. Don't know if you'll be able to add to it after the fact but probably yes.A 'full' property with getter (and setter in this case, though it isn't strictly necessary) will let you do it all in script. struct aStructint helloEndStruct aStruct[] property ArrayOfStructs Hidden aStruct[] Function Get() if ArrayOfStructs == None ArrayOfStructs = new aStruct[0] endif return ArrayOfStructs EndFunction Function Set(aStruct[] value) (<---- this is problematic. You will only be able to pass arrays as arguments, can't just pass structs in there) if ArrayOfStructs == None ArrayOfStructs = new aStruct[0] endif Int i = 0 While i < value.Length ArrayOfStructs.Add(value) i += 1 EndWhile EndFunctionEndProperty This is tedious and clunky as hell so therefor my advice is to create a variable instead if at all possible. aStruct[] ArrayOfStruct ;(<----- outside of Function- or Event-scope, in a script) ;(optional return-type aStruct[]) Function Something(aStruct argument) if ArrayOfStruct == None ArrayOfStruct = new aStruct[0] endif ArrayOfStruct.Add(argument);(optional return ArrayOfStruct)EndFunction You will still be able to access the array from outside of your script. YourScript s s.ArrayOfStruct.Add(sStruct thing)
lee3310 Posted February 7, 2023 Author Posted February 7, 2023 (edited) On 2/7/2023 at 8:01 AM, RaidersClamoring said: A 'single' (jargon) Auto property needs to be populated or at least initialized in CK. Don't know if you'll be able to add to it after the fact but probably yes. A 'full' property with getter (and setter in this case, though it isn't strictly necessary) will let you do it all in script. struct aStructint helloEndStruct aStruct[] property ArrayOfStructs Hidden aStruct[] Function Get() if ArrayOfStructs == None ArrayOfStructs = new aStruct[0] endif return ArrayOfStructs EndFunction Function Set(aStruct[] value) (<---- this is problematic. You will only be able to pass arrays as arguments, can't just pass structs in there) if ArrayOfStructs == None ArrayOfStructs = new aStruct[0] endif Int i = 0 While i < value.Length ArrayOfStructs.Add(value) i += 1 EndWhile EndFunctionEndProperty This is tedious and clunky as hell so therefor my advice is to create a variable instead if at all possible. aStruct[] ArrayOfStruct ;(<----- outside of Function- or Event-scope, in a script) ;(optional return-type aStruct[]) Function Something(aStruct argument) if ArrayOfStruct == None ArrayOfStruct = new aStruct[0] endif ArrayOfStruct.Add(argument);(optional return ArrayOfStruct)EndFunction You will still be able to access the array from outside of your script. YourScript s s.ArrayOfStruct.Add(sStruct thing) Well, to put it mildly, this is not evident. The property struct maybe clunky but it will be very useful in the future. (<---- this is problematic. You will only be able to pass arrays as arguments, can't just pass structs in there)So the argument has to be the same type as the struct ? (i can create an array with one entry and pass it as argumente to circumvent the limitation).Thank you so much for the explanation and in my case, it's better to go with a simple variable instead of property. Edited February 7, 2023 by lee3310
RaidersClamoring Posted February 7, 2023 Posted February 7, 2023 On 2/7/2023 at 5:13 PM, lee3310 said: So the argument has to be the same type as the struct ? (i can create an array with one entry and pass it as argumente to circumvent the limitation). Exactly. I think I'd personally create a global convenience proxy-function that you simply pass one struct, who then wraps it in a temp 1-index array and feeds it to the ArrayOfStructs setter. Declaring, initializing and cleaning up after arrays is a bit of a chore in Papyrus.
lee3310 Posted February 7, 2023 Author Posted February 7, 2023 (edited) On 2/7/2023 at 8:14 PM, RaidersClamoring said: On 2/7/2023 at 5:13 PM, lee3310 said: So the argument has to be the same type as the struct ? (i can create an array with one entry and pass it as argumente to circumvent the limitation). Exactly. I think I'd personally create a global convenience proxy-function that you simply pass one struct, who then wraps it in a temp 1-index array and feeds it to the ArrayOfStructs setter. Declaring, initializing and cleaning up after arrays is a bit of a chore in Papyrus. I will keep that in mind when i will use the property struct you gave me. But for now everything is working great, it's the first time i use a struct so i choose the simple route "variable" and i cleared everything in a timer "StartTimerGameTime(Time, MyActor.GetFormID())"Event OnTimerGameTime(int aiTimerID) While idx < ArrayOfStruct.Length If Game.GetForm(aiTimerID) as actor == ArrayOfStruct[idx].akActor ... ArrayOfStruct[idx].Victim = None ArrayOfStruct.remove(idx) Edited February 7, 2023 by lee3310
RaidersClamoring Posted February 8, 2023 Posted February 8, 2023 On 2/7/2023 at 10:59 PM, lee3310 said: i cleared everything in a timer "StartTimerGameTime(Time, MyActor.GetFormID())"Event OnTimerGameTime(int aiTimerID) While idx < ArrayOfStruct.Length If Game.GetForm(aiTimerID) as actor == ArrayOfStruct[idx].akActor ... ArrayOfStruct[idx].Victim = None ArrayOfStruct.remove(idx) That'll do it. If you are completely done with that struct instance you can clear the whole instance with None as well. Btw I misread you up there -- "So the argument has to be the same type as the struct ?" The argument passed to a property setter has to be the same type as the property itself, i.e. an array in this case. Or at least according to my personal wranglings passing an instance of the type the array contains will fail. If someone knows how, please speak.
lee3310 Posted February 8, 2023 Author Posted February 8, 2023 On 2/8/2023 at 7:19 PM, RaidersClamoring said: On 2/7/2023 at 10:59 PM, lee3310 said: i cleared everything in a timer "StartTimerGameTime(Time, MyActor.GetFormID())"Event OnTimerGameTime(int aiTimerID) While idx < ArrayOfStruct.Length If Game.GetForm(aiTimerID) as actor == ArrayOfStruct[idx].akActor ... ArrayOfStruct[idx].Victim = None ArrayOfStruct.remove(idx) That'll do it. If you are completely done with that struct instance you can clear the whole instance with None as well. Btw I misread you up there -- "So the argument has to be the same type as the struct ?" The argument passed to a property setter has to be the same type as the property itself, i.e. an array in this case. Or at least according to my personal wranglings passing an instance of the type the array contains will fail. If someone knows how, please speak. Yeah i meant same type as the property (struct[]) and it seems logic.
Recommended Posts