So I messed around with the status system tonight. Here's a
You must be registered to see the links
(where I basically take a lap around the second floor of Lilaya's abode as quickly as the game will let me…with 3521 NPCs in the world) and
You must be registered to see the links
.
This is using my
You must be registered to see the links
with a few thousand NPCs, using the traditional Nashorn JavaScript interpreter. I did this in about the simplest way I could think of: status update deferral. Instead of everything being treated equally, there is now an enum to set a status effect to either always be updated (this is used for world-affecting statuses, i.e. pregnancies) or to be updated on-demand (occurs when the player lands on the same tile as the NPC, loads a saved game, and in a few other highly specific situations). This can be set by mods using the optional updatePriority field in the XML (valid values: ALWAYS and ONDEMAND).
This is sorely lacking testing at the moment but the initial results are pretty promising. I tended to err on the side of caution, so I'm sure there are a few situations that are causing spurious on-demand status updates (methinks that's why sleeping is still kinda slow, though that still saw a pretty big speed bump). Naturally, the player's status effects are always calculated at the end of every turn, as are NPCs in a combat/sex scene (comes with the territory, as they will always share a tile with the player).
There are a couple of areas that still need some attention. Clothes and tattoo status effects are currently using the priority system and are only updated on-demand. I'm planning to apply the priority system to those as well. Additionally, there's this little bit of naughtiness that I need to take a deeper dive into:
Code:
// Add all status effects that are applicable:
for (AbstractStatusEffect se : StatusEffect.getAllStatusEffects()) {
if((se.getCategory()==StatusEffectCategory.DEFAULT && (!se.isFromExternalFile() || se.isMod())) // Modded SEs probably won't have taken into account category, so let them always be checked.
|| (se.getCategory()==StatusEffectCategory.INVENTORY && requiresInventoryStatusEffectCheck)
|| (se.getCategory()==StatusEffectCategory.ATTRIBUTE && requiresAttributeStatusEffectCheck)) {
if(se.isRequiresApplicationCheck() && se.isConditionsMet(this)) {
if(!this.hasStatusEffect(se) || se.isConstantRefresh()) {
addStatusEffect(se, se.getApplicationLength()); // Default application length is -1
}
}
}
}
This is…pretty bad. This loops through all of the available status effects in the game and checks to see if inventory or attribute status effects should be applied. The main issue with this is the sledgehammer approach taken, as there are a good number of effects that will likely never get added in this way. Imagine looping through and checking every single status effect in the game at least once for every NPC in the game and it becomes fairly obvious why this isn't a great approach.
In my branch I just added an update priority check to this, but that's a band-aid fix at best (since it's only calling 1 getter for a failed check as opposed anywhere from 3-9). This snippet needs some more TLC.