Jump to content

Tracking Container Contents


Recommended Posts

Apparently, there is no direct way of enumerating/accessing by index a container's contents. So people seem to resort to tracking Item Add/Remove events and updating a separate array of items that are in the container. With the usual, severe drawback of limiting all tracking operations to 128 items max due to the ridiculous 128 elements limit for Papyrus arrays. Seriously, who came up with this limit and thought it was a good idea?

 

Anyway. I tried making a container tracker class based on a formlist instead of an array. Works well, but suffers from another yuuuuge drawback: The FormList must be created in CK, thus all instances of my container tracker then share that same formlist at runtime. Which, of course, completely messes up the tracker's ability to track items across different instances. Furthermore, unless I'm totally mistaken, formlists can't be used with PlaceAtMe() to create instances of them at runtime. Back to square one it is, then.

 

Looking further, I came across the RefCollectionAlias. But it seems the issue with using a refCol is exactly the same as with using a formlist: Instances must be created in CK beforehand and cannot be created a runtime. Sigh.

 

Any suggestions?

Edited by niston
Link to comment
Share on other sites

Yeah, there are a lot of annoying glaring holes in the scripting system, and those are at least two of them.

You can get around this, but it isn't particularly pleasant and requires some ingenuity. It's fun if you are a masochist!

 

For my Papyrus Computer Club mod (that arrived too late for anybody to be aware of), I built an in-world terminal out of paper letters and an in-papyrus interpreter for a very simple BASIC-esque domain-specific programming language so that you can shoot people with programs that you write in game and which are saved to your savegame so that you can do this even on Xbox. To do this required having indexable and modifiable strings, which we also know the game doesn't support.

 

So what I did was create a new EPAString class that derived from an EPAArrayList class, with the former having a small number of string operations like the C Standard Library that I rolled my own on. The EPAArrayList is an object that contains a native Papyrus array and also ObjectReferences to another EPAArrayList. It can be marked as the head node or not the head node, so you may correctly expect that it implements a linked list of arrays. It's a mix between a linked list and a Java-like ArrayList (the list has both a length and a capacity at any one time, with some of the array being dynamically allocated space).

 

You may note at this point that you can't construct objects arbitrarily in Papyrus, because all memory use should be tied to object records. So what I did was create an empty utility cell, place an constant global ObjectReference there as an anchor or monad and use it to spawn physical objects in the void, one for each necessary logical object. EPAArrayLists were breadboxes, EPAStrings were spools of string, EPAStoredPrograms were holotapes, and so on. In this way, I actually used some of that experience implementing data structures from my time in computer science at university. The stored programs were simply array lists of strings with a program counter and a shallow or deep copy operation for managing separate instances of the programs under an interpreter routine. There was a lot of fuss laying out the virtual keyboard as positions hardcoded into the NIF file and managing the character set conversions (arithmetic change of base formulae were in this to handle specifying floating point numbers, also used in the Form F From Address Space mod) and so on...

 

You can't even hardcode a string to be used, so you have to write a separate program to generate Array.Add instructions for any strings you want to hardcode in the system.

 

I also reused these native linked list objects in Mirelurk Merchant (needed for an l-system interpreter that expands the fractal patterns in parallel in-game so they aren't hardcoded in a giant script file), The Maze Ruiner (needed to hold the matrix holding the structs specifying the hedge maze cells and their wall states), and Falling Down (used to construct the Tetris-esque board, but not used to run it because the member-variable lookups were too slow, so I used native Papyrus arrays for hardcoded columns to speed up the computation to where it was semi-playable). Falling Down was also my first script that almost didn't fit in the text editor dialog used in the CK.

Link to comment
Share on other sites

Thanks for chiming in, the blue chicken :smile:

 

I did come across the papyrus computer club mod and thought it to be intriguing. I shall have a closer look at it, I guess...

 

So, a linked list of arrays... That might work...

 

But for now, I rewrote my container tracker to just use an array. I think I will see if I can make it use F4SE's GetInventoryItems(), should F4SE be present. I guess it all comes down to how many stupid hoops one is prepared to jump through, to get the most trivial things done in this truly awful programming environment.

 

Re strings, I'm a little surprised nobody wrote a string handling plugin for F4SE yet.

Edited by niston
Link to comment
Share on other sites

  • Recently Browsing   0 members

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