Typically, when you're talking about stat-management, there are a million ways to accomplish what you're looking to do, but also probably a few established techniques which are widespread.
Consider two players in PvP:
Their stats/levels are the same - they each have 20STR, and HP is based on STR * 10, Damage is STR * 2.
Also assume we're using an old school system, where current max_health and max_damage are caps which can be lowered when poisoned/cold, et cetera.
Lastly, consider division by X to be multiplication by 1/X.
Olag_the_Serious picked up a +15 strength amulet and then got sick.
Jimmy_the_Geek got sick, but then picked up a +15 strength amulet.
Then they fight.
Olag's stats:
STR = (20 + 15) * 0.5 // 17.5
Health = STR * 10 // 175
Damage = STR * 2 // 35
Jimmy's stats:
STR = (20 * 0.5) + 15 // 25
Health = STR * 10 // 250
Damage = STR * 2 // 50
So now we've got this really unbalanced fight between these two characters who have done the exact same things, other than the order of picking up buffs.
How do we fix this?
Break your integer and fractional stats into two groups.
Add the integers.
Then take the final integer and use that as the basis for calculating your fractions.
var finalStat = 0,
fractionalBaseline = 0,
ints = [2, 15, -7],
fractions = [0.2, -0.1, 4];
for each ints as int
fractionalBaseline += int;
end
finalStat = fractionalBaseline;
for each fractions as multiplier
finalStat += Math.floor(frationalBaseline * multiplier);
end
Okay, so the PseudoScript is kinda ugly, but that's the idea.
Now, it doesn't matter what order anything happens in.
We've calculated the baseline with the ints, and then we use the baseline (rather than a running tally) to calculate fractions, which we then convert to ints (totally optional - some games only do that for the user-visible stats), and add them to the final stat.
You might think this is cheating the player, by not adding the fraction to the final tally. What it's really doing is giving everyone a fair experience, because now:
Olag:
STR = (20 + 15) * 0.5 // 17.5
Health = STR * 10 // 175
Damage = STR * 2 // 35
Jimmy:
STR = (20 + 15) * 0.5 // 17.5
Health = STR * 10 // 175
Damage = STR * 2 // 35
It's a fair fight.
Even better, when they get rid of their sicknesses, they'll go back to the same health -- removing an int is simple, but removing a fraction, you convert it to an int based on the current baseline (or float, if you're doing that) and subtract that number.
Just remember that whenever you add an int-bonus, that changes the baseline for the stat, so recompute the fractions, as well.
When you add a fraction, the baseline stays the same.
There's also nothing saying this can't be 100% OOP or Entity/Component-based. This is just the basic concept for arriving at how to have both Boots of Buttkicking (+3 against Butts)
and Almost-Quad Damage (397%)
in the same game, and have it be fair.