Jump to content

[LE] Can you loop through properties? (and/or store properties in an array?)


corrado33

Recommended Posts

If you have a set of aliases to containers why are you looping through them to match them up to some set of form lists? You should be putting a script on each alias that has a formlist property. The script on each alias should be handling the contents of its own container individually. The only array you might want is something to cycle through the aliases to signal that they should all run a particular function. If you're using SKSE then you can even use a ModEvent to signal each of the alias scripts and get all of them working at the same time for maximum performance.

 

P.S. Arrays can be of any length as long as you fill them in the CK instead of creating them in Papyrus even without SKSE.

 

Ah.... I didn't think about it this way.

 

I technically already do half of this. Each alias handle's it's own formlist if an item is added to that specific chest. BUT, if an item is added to the "drop off chest" however, that's handled by the "drop off chest" alias script. But I like your way better. It'll probably be quicker honestly. Instead of having to add every single alias to the drop off chest script, I simply have to add the drop off chest alias to every single individual chest's script. Right now adding every vanilla weapon + every ingredient to the drop off chest takes.... a while to sort though.... I don't know exactly because notifications are slow... I should use messagebox for the final debug line.

 

I like... I like...

 

Although technically I DID just finish the sorting algorighm and what you're suggesting means I have to... re do it.

 

Eh, just thought of something. Your way works assuming all of the individual chests don't... overlap. Say I have a "light armor" chest, but also an "elven material armor" chest. Those two would clash, so I'd have to write special scripts for every individual chest. With exclusions....

 

ORRRR... I could include some empty properties that would be the "exclusions". If they're filled, the script won't run, if they're empty, the script will run.

 

EDIT1: Yeah the script is WAYY too slow right now. It takes 86 seconds to sort through 100 items. This could be optimized a bit more if I made... smarter if statements (check for the most general keywords first, then check for more specific ones inside of those ones, instead of each keyword in its own elseif.) But I think it'd be a lot faster if I did what you suggested.

 

EDIT2: Yeah "HasKeywordString" is SUPER slow. "HasKeyword" with a property setup properly is ~twice as fast. 100 items only takes 46 seconds with "haskeyword" instead of "haskeywordstring."

 

EDIT3: Yeah turns out optimizing your if statements is really.... important. Previously, the check for weapons was the final elseif because.... you know.... weapons starts with "W" and I went alphabetically. If I move the check for weapons to the FIRST if statement, sorting 100 weapons takes 15 seconds. The check for weapons will probably be... 2nd if I keep this type of setup.

Edited by corrado33
Link to comment
Share on other sites

Are you using casts to determine types whenever possible instead of functions?

 

Almost every function including GetType requires a full frame to run because of object locking. This looks efficient.

int type = itemBase.GetType()

if type == 26 ; Armor
  ; do something
else if type == 41 ; Weapon
  ; do something
endif

This actually completes one frame sooner because it doesn't call the GetType function.

if itemBase as Armor
   ; do something
elseif itemBase as Weapon
   ; do something
endif

Every function call you can skip gains you one frame and in a game with a maximum framerate of 60 that means no more than 60 function calls in a second.

 

To get any sort of speed out of manipulating inventory through Papyrus you have to keep function calls to an absolute minimum and make heavy use of dynamic formlists and inventory filters. By dynamic formlists I mean ones that are defined as empty in the CK then filled with specific forms in Papyrus. That allows you to both add and remove items from the lists and avoid the need for an "exclusion" list. If you take the items you don't want to move out of the formlist then you can move large numbers of items that are in the formlist with a single function call and the action happens much more quickly than moving them one by one. When I was still trying to move items using Papyrus for my Storage Helpers mod I came up with a scheme where I had formlists for things to be moved. I had an alias that monitored equipped item changes and would take items out of the weapon, armor, and clothing lists if the item got equipped. Then when a transfer was needed would start be moving everything from the formlist first then cycling through what remained in inventory item by item to decide what to do with it. That way I was always looking through a relatively small set of items one-by-one. The only problem was that that system would grab quest and favorite items. Ultimately I gave up on using Papyrus to move things into and out of the player's inventory and found how to handle moving things by modifying the user interface files instead. (But then I never cared for "auto" sorting that magically put items into specific pre-defined containers. I prefer being able to decide to dump all of my non-favorited potions into a random container of my choice instead.)

Link to comment
Share on other sites

Are you using casts to determine types whenever possible instead of functions?

 

Almost every function including GetType requires a full frame to run because of object locking. This looks efficient.

int type = itemBase.GetType()

if type == 26 ; Armor
  ; do something
else if type == 41 ; Weapon
  ; do something
endif

This actually completes one frame sooner because it doesn't call the GetType function.

if itemBase as Armor
   ; do something
elseif itemBase as Weapon
   ; do something
endif

Every function call you can skip gains you one frame and in a game with a maximum framerate of 60 that means no more than 60 function calls in a second.

 

To get any sort of speed out of manipulating inventory through Papyrus you have to keep function calls to an absolute minimum and make heavy use of dynamic formlists and inventory filters. By dynamic formlists I mean ones that are defined as empty in the CK then filled with specific forms in Papyrus. That allows you to both add and remove items from the lists and avoid the need for an "exclusion" list. If you take the items you don't want to move out of the formlist then you can move large numbers of items that are in the formlist with a single function call and the action happens much more quickly than moving them one by one. When I was still trying to move items using Papyrus for my Storage Helpers mod I came up with a scheme where I had formlists for things to be moved. I had an alias that monitored equipped item changes and would take items out of the weapon, armor, and clothing lists if the item got equipped. Then when a transfer was needed would start be moving everything from the formlist first then cycling through what remained in inventory item by item to decide what to do with it. That way I was always looking through a relatively small set of items one-by-one. The only problem was that that system would grab quest and favorite items. Ultimately I gave up on using Papyrus to move things into and out of the player's inventory and found how to handle moving things by modifying the user interface files instead. (But then I never cared for "auto" sorting that magically put items into specific pre-defined containers. I prefer being able to decide to dump all of my non-favorited potions into a random container of my choice instead.)

 

 

Super.... super good information. Thanks so much. As for speed... if I were able to transfer 100 items in less than 30 seconds, I'd say that's fine. Not super fast of course, but it'll certainly do the job. I think for most people, unless they're specifically going out of their way to collect ingredients, are going to have less than 100 unique items every time they come home. (Because duplicated items don't matter.) I thought about having formlists for every type of item.... and I suppose I still could. Any item added by DLC will be sorted the slow way though. Theoretically if the item is a weapon or armor, it could be sorted in three function calls.

 

As for your "being able to dump everything except favorite potions/weapons/equipped stuff".... I thought about that, and I may implement it. (Basically just be able to add items to a formlist dynamically and then a script on the drop off container will automatically transfer everything BUT those items (excluding quest items of course.) Then obviously my mod will auto sort everything that WAS dumped.) It wouldn't even be that hard, just have a spell that says "everything the player has right now is the "base" list. Everything not on this list gets transferred. Would be slightly harder cause I'd have to deal with item amounts (cause I like to keep 5 potions of each time.)

 

Honestly though, the point of this mod WASN'T to auto sort. It was simply to make an "auto pull" mod that pulls from multiple containers and has support for all of the containers I want. (The dynamic auto sort mod can do this, but doesn't support individual weapon chests (like a chest for daggers, chest for swords, etc.) and the author has no desire to change it.) That mod also only works with ONE crafting station at a time which is.... slightly annoying. (I think it only works with one at a time.) I also REALLY.... REALLY want to implement a "unique" chest that is filled with unique items obviously (because I'm a dum dum and I often sell them.... by accident.)

 

Funnily enough, the previous paragraph is wrong. The point of me starting this type of mod was to make a self dressing mannequin that would automatically pull items out of a chest and dress itself with them. But I didn't know how to dynamically link chests with mannequins. Now, this may sound stupid, but my idea was for the "player owned store." And a store should have rotating stock, and this would make sense. I haven't actually... made that mod yet, bud I did make an auto mannequin switch clothes script that you activate by sneak-activating a mannequin then all your equipped items are put on the mannequin and all the mannequin's equipped items are put on you.

Edited by corrado33
Link to comment
Share on other sites

Oh, well, if it's a mannequin that works with a *store* you want, I've been working on something along those lines for literally years now :v

 

Oh yeah? Is it.... published? Sometimes searching for things on the nexus is... hard.

 

The store I've used is the drunken dragon mod, which I find to be a nice... lore friendly way to sell all of your loot (although I tweaked the sell function a bit, more expensive items sell less often, and if someone buys a piece of armor there is a chance they'll buy a whole set of armor.)

Link to comment
Share on other sites

No, it's not published -- every time I think I get close, I come up with new things I want to try and do to make it usable by other modders :sad: --, and it may not be quite what you're after because it's designed to hook into Skyrim's NPC vendors, and consequently vendor chests. But it does mean I've been up to my eyebrows in mannequin and chest inventory manipulation and equipping for a long time. and so there's a good chance I can help you with things.

 

Lay out the skeleton of how this store is supposed to work, I'll see if I can share what I've learned.

Edited by foamyesque
Link to comment
Share on other sites

No, it's not published -- every time I think I get close, I come up with new things I want to try and do to make it usable by other modders :sad: --, and it may not be quite what you're after because it's designed to hook into Skyrim's NPC vendors, and consequently vendor chests. But it does mean I've been up to my eyebrows in mannequin and chest inventory manipulation and equipping for a long time. and so there's a good chance I can help you with things.

 

Lay out the skeleton of how this store is supposed to work, I'll see if I can share what I've learned.

 

Oh thanks, I'm not quite working on that yet though :) What... exactly does your mod do? Buy stuff from vendors?

Link to comment
Share on other sites

 

No, it's not published -- every time I think I get close, I come up with new things I want to try and do to make it usable by other modders :sad: --, and it may not be quite what you're after because it's designed to hook into Skyrim's NPC vendors, and consequently vendor chests. But it does mean I've been up to my eyebrows in mannequin and chest inventory manipulation and equipping for a long time. and so there's a good chance I can help you with things.

 

Lay out the skeleton of how this store is supposed to work, I'll see if I can share what I've learned.

 

Oh thanks, I'm not quite working on that yet though :smile: What... exactly does your mod do? Buy stuff from vendors?

 

 

Conceptually, it's straightforward: I wanted working display mannequins added to armour & clothing vendors, like Radiant Raiment or Warmaidens. There'd be mannequins in the store, which would have a set of outfits they would display. They'd refresh regularly, equip it, and you could walk up and either buy it from the merchant, through activating the mannequin or talking to the merchant directly, or try to steal from them.

 

The mechanics of getting that *working* were, uh, not straightforward. :D

Link to comment
Share on other sites

 

 

No, it's not published -- every time I think I get close, I come up with new things I want to try and do to make it usable by other modders :sad: --, and it may not be quite what you're after because it's designed to hook into Skyrim's NPC vendors, and consequently vendor chests. But it does mean I've been up to my eyebrows in mannequin and chest inventory manipulation and equipping for a long time. and so there's a good chance I can help you with things.

 

Lay out the skeleton of how this store is supposed to work, I'll see if I can share what I've learned.

 

Oh thanks, I'm not quite working on that yet though :smile: What... exactly does your mod do? Buy stuff from vendors?

 

 

Conceptually, it's straightforward: I wanted working display mannequins added to armour & clothing vendors, like Radiant Raiment or Warmaidens. There'd be mannequins in the store, which would have a set of outfits they would display. They'd refresh regularly, equip it, and you could walk up and either buy it from the merchant, through activating the mannequin or talking to the merchant directly, or try to steal from them.

 

The mechanics of getting that *working* were, uh, not straightforward. :D

 

 

Oh geeze, I bet... I mean I think the hardest part would be to find the items that the vendor is selling correct? Other than that, making a mannequin dress with items from that list (should be?) easy enough, a few if statements and equipitemex with an onload event. However, being able to steal them.... that'd be hard. I think.... very hard. Since mannequins are essentially NPCS stealing from them would be essentially pickpocketing from them and you'd have to override that and THAT'D be hard. I guess you could make them owned by the store NPC, but I've never tried that. Or you could make the mannequin activator have a custom activate message when the player is crouching. I think that'd be easy enough. (Maybe?) And being able to buy them from the mannequin would be... interesting. A few ways you could probably do it. Make a dynamic message box (is that... possible?) with the name of the armor set and the price and a simple "Buy" or "Do not buy". Or you could simply make it an activator for talking with the store npc. (I'm still.... awful with activators, so I have no idea if that's possible.)

 

Sorry, I love spitballing program ideas. Fun stuff :)

Link to comment
Share on other sites

Good insight on the pickpocketing thing. Of course, mannequins don't have names, so you can't actually activate them normally, and there's no way I ever found to script-wise bring up the pickpocket menu, so what I wound up doing was creating a new mannequin with an actual name and using a perk to override the activation text for pickpocketing (learning in the process that Skyrim notifications accept limited HTML) and provide a custom activation sequence for normal activation, to pull up the barter menu. In order to make that work I needed to get rid of the activation triggerbox as well.

 

Sync'ing up with the vendor chests in such a way as to allow multiple mannequins to talk to it, as well as the possibility of edits made by other mods, was frustrating.

 

Skyrim does not allow a vendor to have multiple vendor factions, nor any vendor faction to have multiple chests, so you're left with finding some way to insert your items into the one existing chest in an extensible manner -- which means you can't edit it directly. I considered reading what was already in the chest and using that to dress a mannequin, but decided against it, on a few grounds.

 

Merchant chests refresh when the player talks to the merchant (if enough time has passed since the last refresh), which means that if you set up something that re-dresses the mannequins on refresh of the chest, if it's to stay sync'd with the chest, the player would see the mannequins all spontaneously change their gear at once. A reliable way of detecting merchant chest refreshes can be done via adding a non-playable token and watching for its disappearance, but it's a kludge, and in any case I wanted to provide for people perhaps not wanting the mannequin to change at the same intervals as the merchant chest in any case. And, also, I had in some cases very specific gear I wanted any particular mannequin to display: Wolf Armour for Eorlund, Stormcloak in Windhelm, Imperial in Solitude, and so on. In general, I also usually wanted things to be displayed as a set, which the vanilla merchant chests usually don't provide for.

 

So ultimately what I did was create custom levelled lists for the mannequins, with what I wanted that particular mannequin to be choosing from, and the mannequins themselves had customizable timers. Every X hours, as long as the player's not nearby, they nuke their prior gear, and then add and equip the refreshed stuff.

 

So that can generate the 'what the mannequins wear' piece. But the next step's making it available for sale: it has to be added to the merchant chest (or dropped into the world as a loose item, as I feared might have to be done). Adding it directly by scripting doesn't work, because the refreshes obliterate it and even if you do the kludge-token solution to wait for a refresh and *then* add it you're doing so *after* the player has opened the barter menu, which isn't great. Adding them through directly editing the chest in the CK doesn't work, because in many cases the loot's leveled and randomized so you'd get different results on the mannequin v. the chest, and in any case that approach means any other mod that wants to edit the chest will be in conflict.

 

What I wound up doing was making use of the Quest Alias inventory tab. All the merchant chests already needed to be aliased in any case to provide for OnItemRemoved events to detect when a mannequin's items were purchased and remove the relevant things from them. And stuff added through an alias' inventory tab persists through refreshes (it's used in the base game for things like the Beacon of Meridia for that reason), so it doesn't matter when something is added by that method to the chest; it will be available to the player.

 

The problems there are: First, that what is in that tab can't be edited at run time, and second, by default, it doesn't refresh. It'll be what it's set to at when the alias is filled and stay that way until the player takes it, but won't ever replace what's removed.

 

I found ways around both. Leveled lists can be edited through scripts, and you can use leveled lists in those tabs, so I created a separate, unique, empty leveled list for each merchant chest's alias. The merchant chest alias gets squirted the inventory data from all the mannequins that belong to it when they refresh, clears whatever was in its leveled list before, and then adds all the new stuff as guaranteed, non-random loot.

 

This, by itself, doesn't do anything; editing the leveled list after it has been evaluated and provided the items to whatever filled the alias is just data manipulation. But it gets evaluated every time the alias is filled, and clearing, and then using ForceRef(), counts as filling the alias. So, once you've edited the leveled list, you blink the chest in and out of the alias, and bam, refreshed and reset-proof inventory. Trouble is all the old stuff's still there, so you need to remove it yourself, which requires some inventory tracking if you want to do it cleanly.

 

Because of the possible simultaneity of some of these events, f'rex three or more mannequins refreshing at the same time or the player deciding to buy everything in a store at once, even the above is not as simple as it sounds. :(

Link to comment
Share on other sites

  • Recently Browsing   0 members

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