Multistate Attributes Bug
docemoon145
25 Aug 2018, 20:01I made a garment in Quest that had multiple states. I thought I had everything working just fine, until I noticed something subtle but devastating.
Once the cursed garment reaches its highest multistate setting, the player's max health decreases by 1. That attribute "bonus" is only supposed to last as long as the garment is in the right state and worn, right? But when I take the garment off, the player's health is still decreased by 1. And if I put it on again, it goes down another point! The cursed item is supposed to be annoying, but this could literally kill the player. Is this the way quest is supposed to handle multistate bonus attributes? It feels like a bug to me.
If it is a bug, then the player could also just re-wear an armor with good bonuses until their stats are game-breakingly high. I would really appreciate some sort of fix for this.
Thanks in advance.
mrangel
25 Aug 2018, 21:19It should remove the "bonus" without problem. I just walked through the code for this, and I can't see how a bug could occur.
Is the player removing the garment using the remove command, or are you calling RemoveGarment from a script?
(If you are setting somegarment.worn = false
, that's the problem. To remove a garment from a script, you need to call either _DoRemove(garment)
(which checks to see if they're actually wearing it and are allowed to remove it, as if they'd used the remove command), or RemoveGarment(garment)
(which doesn't check, so will subtract the bonuses from the player's stats even if the garment wasn't worn to start with))
docemoon145
26 Aug 2018, 18:38I'm using RemoveGarment() from the object's verb list.
Okay, I have an idea where the issue may be coming from, so it's probably not a bug. See, I allow the garment's curse multistate status to change without the player's direct control. So, every time they use a different cursed object, I call WearGarment() again to reset the multistate value and the alias and all that. But every time I do that, it must be reapplying all the bonuses too. The reason I didn't notice sooner is probably because only the max multistate setting decreases the player's max health.
In other words, one call to RemoveGarment() isn't enough to remove all the stacked bonuses. I can probably fix the issue if I make a special function, say UpdateGarment(), that removes the old bonuses before applying the new ones. I hope that will work.
mrangel
26 Aug 2018, 19:23I suggested a way to fix this issue in another thread yesterday. Haven't tested it, but it might help you.
Basically, I changed the SetBonuses()
function to do nothing; made a new function ApplyBonuses()
, and added 3 script attributes (changedparent
, changedworn
, and changedbonusatts
) to the wearable
type.
These scripts call ApplyBonuses
to add bonuses to the player's stats whenever its "worn" attribute becomes true, regardless of whether that's because of a verb or a fuinction call; to remove the bonuses when "worn" becomes false; and to remove the old bonuses and apply the new ones (if it is worn) whenever the bonusatts
is changed, whether that's because its multistate has changed or because a script has changed the bonuses of a wearable for some other reason. It also removes the bonuses and sets "worn" to be false if a script teleports some garment away from the player.
I think this is the way it should have been implemented in the first place, because it fixes a lot of edge cases so it just works. Unfortunately, I can't propose moving this into the Quest core in the next version, because it would introduce bugs for anyone who's modified both the SetBonuses
and WearGarment
functions already.
My suggestion was here: [link] - not tested, but might be a decent point to start if you're having to mess around with the wearables system anyway.
mrangel
26 Aug 2018, 19:35I can probably fix the issue if I make a special function, say UpdateGarment(), that removes the old bonuses before applying the new ones.
Isn't that what SetMultistate(garment, state)
does?
docemoon145
27 Aug 2018, 00:28Oh wow! It's almost exactly the function I was about to write! I'm glad you brought it up because I didn't know it existed. I'll have to tweak a few things for my purposes, but this should speed things up quite a bit.