Kapteyn Posted September 29, 2017 Share Posted September 29, 2017 I've started to put everything into form lists rather than plugging everything directly into the virtual adapter. So in the script I'll simply link to the forms. Say for example I've got 10 object references in a form list, but on the virtual adapter the only single object entry is the form list, so then I reference the array in the script to grab the forms. So which is the best method? I prefer using form lists, it seems tidier and it's certainly easier for me to organise stuff. Link to comment Share on other sites More sharing options...
JonathanOstrus Posted September 30, 2017 Share Posted September 30, 2017 (edited) I've started to put everything into form lists rather than plugging everything directly into the virtual adapter. So in the script I'll simply link to the forms. Say for example I've got 10 object references in a form list, but on the virtual adapter the only single object entry is the form list, so then I reference the array in the script to grab the forms.So which is the best method? I prefer using form lists, it seems tidier and it's certainly easier for me to organise stuff.Requesting a single entry from a form list is slower than referencing a property. If you're not doing it frequently speed probably won't matter too much. Though it could logically be easier to understand if directly defined as a property instead of an entry on the list. Ultimately it will depend on how the code uses it, needs to access it, and how frequently. If you can do it either way I'd say do whichever is more comfortable for you. But think ahead in case you may need to change something in the future. One method vs the other may lend to making that easier or not possible depending on the implementation. Edited September 30, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
cdcooley Posted September 30, 2017 Share Posted September 30, 2017 You're using too many non-standard terms or using terms in non-standard ways. Please don't make modding more difficult for other people. VMAD and the virtual adapter are terms specific to TES5Edit and you should be talking about filled script properties instead. A FormList is not an array which is important because arrays are a third choice. Are you using "object reference" as a generic term for Form or are you specifically talking about an ObjectReference? There are three main ways you can declare a group of things in scripts, here are some of the advantages, disadvantages, and other features of each. Individual properties Advantages:Access is fast.Each can be of a different type.When named correctly the CK can auto-fill them.Easy to use for beginners. Disadvantages:Each property name is an entry in the string cache.Each property must be accessed individually. Other:Any ObjectReference (including Actor) placed in a property makes that reference persistent in the game. FormList properties Advantages:Only one string cache entry for the entire group.Forms can be added by dragging them into the FormList in the CK.Related groups can be kept together.There are a number of functions that can work on the entire set of forms in a FormList.Each form in the list can be of a different type. Disadvantages:Access is slow unless you are using a function which works on the entire FormList at once.FormLists can't have duplicates and order/position of forms added by scripts can't be guaranteed. Other:Forms added to the FormList in the CK can't be removed from the lists by scripts.FormLists can be altered by scripts while the game is running.ObjectReferences placed in a FormList are not made persistent automatically. Array properties Advantages:Access is almost as fast as accessing a local property.Related groups can be kept together.Only one string cache entry for the entire group.The array's find method is fast. Disadvantages:While you can have an array of Form type you can't fill it from the CK. Only more specific types like Armor or ObjectReference can be filled by the CK.Array sizes are fixed. Entries can be changed but new entries can't be added.Arrays can be filled from the CK but not with auto-fill and not with drag-and-drop.Most functions don't accept array properties as arguments. Other:ObjectReferences added to an array will be made temporarily persistent. Note: The importance of ObjectReference persistence is that only objects currently loaded into memory can be manipulated by scripts. If an non-persistent object is in some other game cell that isn't currently loaded script attempts to access the object will generate errors. The CK automatically flags any ObjectReference used to fill some script property as persistent to prevent script errors. References placed in arrays are also temporarily tagged as persistent but no special tagging is done for things in a form list. If your real goal is to avoid filling properties in the CK because you do most of your modding in TES5Edit then you should not be using FormLists. But if you're trying to organize groups of related properties then FormLists and Arrays can be very helpful. Link to comment Share on other sites More sharing options...
foamyesque Posted September 30, 2017 Share Posted September 30, 2017 cdcooley: You absolutely can have an array of Forms, even in a property; you just can't fill it in the CK. I know you know this, but to make it clear to anyone else finding this in the future. Link to comment Share on other sites More sharing options...
Kapteyn Posted September 30, 2017 Author Share Posted September 30, 2017 (edited) Thank you, cdcooley... that's a lot of useful info. Admittedly I'm not entirely clued up on the technical terms, as has probably been gathered. I'm not specifically referring to Object References, at least I don't think I am. What I'm doing is sticking a bunch of stuff into one form list, those things might be different - say for example I have some globals and a few choices of levelled actor, whichever actor is selected depends on the global values. So I just call the form list in the script during init and reference them that way (there's no function, it's all done pretty quickly and I delete the object at the end of it). I'm guessing it's a long way about it but at the same time I've noticed the overall file size of the plug-in and scripts combined has decreased since I've been doing this, which is why I wonder if it's saving on resources. As for an array, I assumed that because the form list is exactly that, a list, if I'm looping through them then surely I'm doing exactly the same thing as looping through an array? Either way, it doesn't sound like something which would work with what I'm trying to do, not if an array is limited to certain types. Now one thing which interests me is the persistent nature of properties, I didn't think about this. Basically, I'm using dummy objects to spawn stuff (specifically, I'm hooking scripts on activators), those dummies are deleted as soon as they're done - so what I don't need is for the save game to become bloated with redundant references to hundreds or even thousands of dead things that never even lived in the first place. Also, everything which happens is in the active cell, I'm not concerned with anything outside of the immediate space. I predominantly use TES5Edit, I only really switch to CK to add new scripts or entries. But it does so happen that the naming convention I use works well with CK to auto-fill, I never really thought about how this works but it does. Edited September 30, 2017 by Kapteyn Link to comment Share on other sites More sharing options...
Kapteyn Posted September 30, 2017 Author Share Posted September 30, 2017 (edited) Okay, here's a rather basic example... ScriptName Spawner_Wolf Extends ObjectReferenceFormList Property FLST_SpawnWolf AutoEvent onInit() GlobalVariable Enabled = FLST_SpawnWolf.GetAt(0) As GlobalVariable If Enabled.GetValueInt() > 0 Self.PlaceAtMe(FLST_SpawnWolf.GetAt(1) As ActorBase, 1) EndIf Self.Delete()EndEvent(fixed verison) Edited September 30, 2017 by Kapteyn Link to comment Share on other sites More sharing options...
foamyesque Posted September 30, 2017 Share Posted September 30, 2017 The difference between arrays and formlists in terms of speed goes to how they're implemented in the background. The ways that a formlist is accessed are safe, but they're frame-rate sync'd and slow. Array manipulation is blazing fast by comparison, since they're not framerate sync'd, but they're not thread safe so you need to be careful. They're the fastest way to manipulate large amounts of data by far, but if you're needing to talk to default game systems (e.g. the conditions system) you need to dump it back out into a FormList. There's SKSE functions that exist to make this much less painful (and allow you to blast past the 128-element limit Papyrus ships with). Link to comment Share on other sites More sharing options...
JonathanOstrus Posted September 30, 2017 Share Posted September 30, 2017 (edited) Okay, here's a rather basic example... ScriptName Spawner_Wolf Extends ObjectReference FormList Property FLST_SpawnWolf Auto Event onInit() If FLST_SpawnWolf.GetAt(0) As GlobalVariable ; is enabled? Self.PlaceAtMe(FLST_SpawnWolf.GetAt(1) As ActorBase, 1) EndIf Self.Delete()EndEvent I'm not going to get into whether it is proper to use a formlist in this way or not. If this is a real code sample I don't think you have your if statement correct. All it's checking is if the form entry at index 0 can be cast as a GlobalVariable. It doesn't check the value of it which I think is what you probably intend for it to do. It would also spit out papyrus errors to the log if you don't have a 0 index entry, ie you didn't fill the property or the list is entirely empty. Though not a code breaking problem it's a peeve of mine. I like error checking in code. I would write the if statement like this If FLST_SpawnWolf.GetSize() > 0 && FLST_SpawnWolf.GetAt(0) As GlobalVariable && (FLST_SpawnWolf.GetAt(0) As GlobalVariable).Value != 0.0This code shouldn't need any explanation about how it works. Edited September 30, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
cdcooley Posted September 30, 2017 Share Posted September 30, 2017 cdcooley: You absolutely can have an array of Forms, even in a property; you just can't fill it in the CK. I know you know this, but to make it clear to anyone else finding this in the future.Yes, I should have been more precise, but I was thinking about the relative benefits of FormLists vs. arrays. I'll fix that. Link to comment Share on other sites More sharing options...
Kapteyn Posted September 30, 2017 Author Share Posted September 30, 2017 (edited) if you're needing to talk to ... the conditions system ... you need to dump it back out into a FormList. Actually yes, conditions are a major part of this, hence the use of global variables. If this is a real code sample I don't think you have your if statement correct. All it's checking is if the form entry at index 0 can be cast as a GlobalVariable. It doesn't check the value of it which I think is what you probably intend for it to do. It would also spit out papyrus errors to the log if you don't have a 0 index entry, ie you didn't fill the property or the list is entirely empty. Though not a code breaking problem it's a peeve of mine. I like error checking in code. It is working code. I'll run some tests on it, I'll flip the global to see if the thing spawns or not. I assumed what I was doing was effectively running a bool check on the variable. If the list doesn't exist or its empty then it's going to return a null, if the global is zero then it'll return as false and a positive integer is true (I still dunno if a negative counts as true or false, I think it depends on the language). The thing is, as soon as multiple conditions are being used, like checking the list is not empty, checking an entry is a global, etc... surely that's the point at which it becomes pointless to use a form list in such a way? I mean, in the case of me using my own code the onus is on myself to not use an empty list, to ensure that what is being called or passed is valid in the first place. But yes, I absolutely understand the concept of error-proofing because I've done a fair bit of work with PHP in the past - when it comes to web code and especially SQL, we don't want unexpected data being passed to a function because a slight oversight might be as simple as the server crashing but then there's security. This isn't as critical, nobody's computer is going to break, but clean code is a virtue after all. Having said that, if people are going to pass a null then it's not the function which is at fault. I suppose it's better to catch it if possible, but it's no different to somebody using a null property rather than a placeholder, the script expects a value and it doesn't get one. How can the script check if it's null without throwing an error? If thing != none (oops, your $thingy is null so have yourself a nice error) Or am I overlooking something? So actually, now that I think about it... what this really needs is a function to validate the request. Function ValidateThing(formlist, index, type) Then it checks to see if the form exists, if there is data at 0, if it can cast, etc. I still think it's pointless though because it's adding overhead. As soon as we're validating everything it's probably better to simply use properties, but this leads me back to the issue with persistent data. Edited September 30, 2017 by Kapteyn Link to comment Share on other sites More sharing options...
Recommended Posts