7 ms·
> IMO the best approach for business logic values is picking the smallest meaningful unit and representing it with integers. How would you design an RTS unit s
by DaiPlusPlus 4y ago
> IMO the best approach for business logic values is picking the smallest meaningful unit and representing it with integers.
How would you design an RTS unit stats system to avoid this AoE Monk HP bug using only integer types?
- bruce343434 4y agoHow much health precision do you need? Make hp an int. Or like a /64 fixed point.
- account42 4y agoCongratulations, you just introduced a new damage threshold / resistance threshold / etc where things effectively do no damage. Fixed point would not have helped here. Integer would only have helped because dividing first would break immediately.
- falcor84 4y agoWell, in this case, if a unit is converted to a different type and back, it would just keep its (absolute) value of HP (in this case 1), no need to scale anything.
- db48x 4y agoYou haven’t thought it through yet. In this case, HP _is_ an integer, and so is the MaxHP for the unit type. And yet the bug still occurs! Storing the HP as an integer does not prevent the problem from ever occurring, because fundamentally the user still expects HP to be proportional. That is, suppose a unit is sitting there at full health, and you research a tech that increases that unit’s max hp? Should the unit now be at less than full health, as if it had been in combat? Users probably don’t like that. Suppose it is at full health, and then it gets downgraded to a type with less maximum health. Does it stay at it’s current HP? Users probably won’t like being attacked with supercharged units that have extra HP; they’ll think that the other player was cheating somehow. What if it is damaged and at half health, then gets upgraded. Should it be fully healed? Gain HP equal to the difference between the new and old maximum HP? Or should it gain half of that, so that it stays at half health? Or perhaps HP is too limiting, and the game should do what Dwarf Fortress does. DF knows the approximate surface area of every body part (based on each creature’s body plan, plus individual stats such as strength, fatness, size, etc), and the size of every weapon. Every attack therefore deals damage to a certain area, measured in square inches, and individual body parts will be destroyed once a sufficient percentage of that surface area is damaged by wounds. Or maybe you are designing this game in the 90’s, and you have to worry about squeezing unit updates for 200 units per player into the bandwidth provided by the average modem of the day (probably 28.8kbaud), so you stick to one integer because it’s the simplest think that can possibly work, and the number of bytes per update can be calculated in advance. And then some other schmuck gets stuck with the job of handling unit type changes (but be warned that the schmuck might be yourself in six months).
- ilyt 4y ago>That is, suppose a unit is sitting there at full health, and you research a tech that increases that unit’s max hp? Should the unit now be at less than full health, as if it had been in combat? Users probably don’t like that. >Suppose it is at full health, and then it gets downgraded to a type with less maximum health. Does it stay at it’s current HP? Users probably won’t like being attacked with supercharged units that have extra HP; they’ll think that the other player was cheating somehow. >What if it is damaged and at half health, then gets upgraded. Should it be fully healed? Gain HP equal to the difference between the new and old maximum HP? Or should it gain half of that, so that it stays at half health? if (oldHP == maxOldHP) { newHP = newMaxHP } else { newHP = max(1,scale(oldHP,oldMaxHP,newMaxHP)) not exactly complex
- ghusbands 4y agoSure, if you fully predict all bugs in advance and compensate for them, nothing is complex, but that's not really feasible.
- mrguyorama 4y ago>Sure, if you fully predict all bugs in advance and compensate for them, nothing is complex, but that's not really feasible. Uhh, last time I checked, that was literally my job, and specifically what I went to school for!
- db48x 4y agoNot exactly complex, but you posted too quickly to have found the best solution. A better solution is to kill the unit when it drops below zero HP, not when it drops below 1.0; scaling will never move the current HP past zero in either direction. Having 0.9999994 HP instead of 1.0 HP would not cause any problems then; the unit is still one hit away from death in either case. The best solution is probably to store the current HP as a percentage of the max, because then you never have to rescale it in the first place.
- 4y ago
- CodesInChaos 4y ago`(new_maxhp * old_hp) / old_maxhp` avoids the original problem when using integers. Though you still need to make sure your type is big enough to not overflow. Or using fixed-point (which are a relatively simple abstraction over integers): `old_hp * (new_maxhp * old_maxhp)`.
- rvnx 4y agoThey probably just added: return ROUND()... and went back to play
- ilyt 4y agomax(1,...