lee3310 Posted February 7, 2023 Share 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 Link to comment Share on other sites More sharing options...
RaidersClamoring Posted February 7, 2023 Share 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) Link to comment Share on other sites More sharing options...
lee3310 Posted February 7, 2023 Author Share Posted February 7, 2023 (edited) 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 Link to comment Share on other sites More sharing options...
RaidersClamoring Posted February 7, 2023 Share Posted February 7, 2023 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. Link to comment Share on other sites More sharing options...
lee3310 Posted February 7, 2023 Author Share Posted February 7, 2023 (edited) 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 Link to comment Share on other sites More sharing options...
RaidersClamoring Posted February 8, 2023 Share Posted February 8, 2023 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. Link to comment Share on other sites More sharing options...
lee3310 Posted February 8, 2023 Author Share Posted February 8, 2023 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. Link to comment Share on other sites More sharing options...
Recommended Posts