RPG damage computation math
I'd like to state some rules of my RPG in the following way:
"Each time a character lands a hit, the weapon modifier should determine up to 60% of the damage, strength should determine up to 20% and dexterity up to 20%. The damage must always be an integer from [dmg_low, dmg_high]."
Is there a general formula for doing this computation?
I know, my formulation of the goal isn't probably the best, and has several different interpretations. For example, where does the random element come in? (We don't want the game to be deterministic).
One possible way is to define 3 random variables:
X1 = {0,...,weapon}
X2 = {0,...,str}
X3 = {0,...,dex}
(weapon is the character's current weapon modifier, etc.)
With every value being equally possible, i.e. P( X1=i ) = (1/weapon) (in other words, X1 is simply a fair (weapon)-sided dice.)
So the best possible result is that every random variable gives the maximum value:
max = weapon + str + dex
And now I want to create the damage function D, such that X1 contributes 60% to the value of D, X2 contributes 20% and X3 also 20%. Additionally, D needs to be an integer from [dmg_low, dmg_high].
D(X1,X2,X3) = ?
How can I do this? It sounds simple enough, but I'm out of ideas.
If you just want "Up to", Random.Double * 0.6, * 0.2, * 0.2 in your favorite RNG will do that.
If you want them each to contribute exactly 60%, 20% and 20%, your best bet is just to RNG a number between 0.0 and 1.0 and multiply Weapon * 0.6 * N, Strength * 0.2 * N and Dexterity * 0.2 * N.
If you want them each to contribute 60%, 20% and 20%, no matter what number they roll - Statistically, that doesn't make sense to me. Although, I'm not a statistician.
If you want them each to contribute exactly 60%, 20% and 20%, your best bet is just to RNG a number between 0.0 and 1.0 and multiply Weapon * 0.6 * N, Strength * 0.2 * N and Dexterity * 0.2 * N.
If you want them each to contribute 60%, 20% and 20%, no matter what number they roll - Statistically, that doesn't make sense to me. Although, I'm not a statistician.
You want the damage to be 0-20%*Strength + 0-20%*Dextery + 0-60%*Weapon?
If so(I assume you know how to generate a random float):
//random number generator in c
float Rf(float min, float max)
{
if (min>max){float tmp = min; min = max; max = tmp;}
return min + (rand() / float(RAND_MAX)) * (max - min);
}
//
Damage = Rf(0,0.2) * Strength + Rf(0,0.2) * Dextery + Rf(0,0.6) * Weapon;
You could just let your damage function return the damage directly.
If you need to find the min and max damage:
For the minimum you have to add all the lowest possible values for the maximum all the highest.
minimum = 0 * Strength + 0 * Dextery + 0 * Weapon; // == 0
maximum = 0.2 Strength + 0.2 Dextery + 0.6 Weapon;
Since you wrote "each attribute contributes x% to Damage" i fear you might mean something different.
If you mean
Damage = x *STR + y *DEX + z *WEA;
and x + y + z = 100%
in that case, you would be achieving nothing by making it that complex. You would still get a constant minum and maximum damage which would develop in a linear fashion.
I think what you are trying to do with a system like that is to weight the ranges like: A strong person with weak weapon has a 90% probability of doing 5 - 10 Damage but a 10% probability of doing 50 - 100 damage.
But thats not happening because with this system each number between min and max would have the same probability and min and max keep constant. Its just more confusing.
Anyways, I think you want to know how to split up something in %, and thats something useful to know(eventhough it would be misapplied here).
The catch is that the sum of the percent parts always has to be 100%. So if you have 0 - 20% + 0 - 20% + 0 - 60% guess what the only possible way to divide is 20% 20% 60%. So if you want different results you would have to do something like 0 - 20% 0 - 100% 0 - 80%
Heres how I would do this:
each percent = Random (lowest_possible_number, highest_possible_number)
example:
Divide D into Strength Dextery and Weapon.
Strength = 0 - 20%
Dextery = 0 - 100%
Weapon = 0 - 80%
pseudocode:
strengthmin = 0; strengthmax = 0.2;
dexterymin = 0; dexterymax = 1.0;
weaponmin = 0; weaponmax = 0.8;
//if we use different minimas than zero we need to add a little bit code, but I dont want to be too confusing
undivided_percent = 1;
necessary_minimum = 0;
//does the next variable need to have a minimum so we can reach 100%
//If not this will result negative or 0
necessary_minimum = undivided_percent -dexterymax -weaponmax;
if (strengthmin<necessary_minimum)
{
strengthmin = necessary_minimum;
}
//How much % can we still give away? At this time this will be 100%
//And will not affect our maximum
if (strengthmax>undivided_percent)
{
strengthmax = undivided_percent;
}
Strength = Random(strengthmin,strengthmax);
//and now we substract the % we have given away, so we can calculate the
//maximum of dextery and weapon
undivided_percent -= Strength;
// and now well do the same stuff for dextery
necessary_minimum = undivided_percent - weaponmax;
if (dexterymin<necessary_minimum)
{
dexterymin = necessary_minimum;
}
if (dexterymax>undivided_percent)
{
dexterymax = undivided_percent;
}
Dextery = Random(dexterymin,dexterymax);
undivided_percent -= Dextery;
// and the last one gets whats left
Weapon = undivided_percent;
Hope you get the idea, I cant guarantee that I did not make a mistake and you can do this prettier (depending on the language your using).
If so(I assume you know how to generate a random float):
//random number generator in c
float Rf(float min, float max)
{
if (min>max){float tmp = min; min = max; max = tmp;}
return min + (rand() / float(RAND_MAX)) * (max - min);
}
//
Damage = Rf(0,0.2) * Strength + Rf(0,0.2) * Dextery + Rf(0,0.6) * Weapon;
You could just let your damage function return the damage directly.
If you need to find the min and max damage:
For the minimum you have to add all the lowest possible values for the maximum all the highest.
minimum = 0 * Strength + 0 * Dextery + 0 * Weapon; // == 0
maximum = 0.2 Strength + 0.2 Dextery + 0.6 Weapon;
Since you wrote "each attribute contributes x% to Damage" i fear you might mean something different.
If you mean
Damage = x *STR + y *DEX + z *WEA;
and x + y + z = 100%
in that case, you would be achieving nothing by making it that complex. You would still get a constant minum and maximum damage which would develop in a linear fashion.
I think what you are trying to do with a system like that is to weight the ranges like: A strong person with weak weapon has a 90% probability of doing 5 - 10 Damage but a 10% probability of doing 50 - 100 damage.
But thats not happening because with this system each number between min and max would have the same probability and min and max keep constant. Its just more confusing.
Anyways, I think you want to know how to split up something in %, and thats something useful to know(eventhough it would be misapplied here).
The catch is that the sum of the percent parts always has to be 100%. So if you have 0 - 20% + 0 - 20% + 0 - 60% guess what the only possible way to divide is 20% 20% 60%. So if you want different results you would have to do something like 0 - 20% 0 - 100% 0 - 80%
Heres how I would do this:
each percent = Random (lowest_possible_number, highest_possible_number)
example:
Divide D into Strength Dextery and Weapon.
Strength = 0 - 20%
Dextery = 0 - 100%
Weapon = 0 - 80%
pseudocode:
strengthmin = 0; strengthmax = 0.2;
dexterymin = 0; dexterymax = 1.0;
weaponmin = 0; weaponmax = 0.8;
//if we use different minimas than zero we need to add a little bit code, but I dont want to be too confusing
undivided_percent = 1;
necessary_minimum = 0;
//does the next variable need to have a minimum so we can reach 100%
//If not this will result negative or 0
necessary_minimum = undivided_percent -dexterymax -weaponmax;
if (strengthmin<necessary_minimum)
{
strengthmin = necessary_minimum;
}
//How much % can we still give away? At this time this will be 100%
//And will not affect our maximum
if (strengthmax>undivided_percent)
{
strengthmax = undivided_percent;
}
Strength = Random(strengthmin,strengthmax);
//and now we substract the % we have given away, so we can calculate the
//maximum of dextery and weapon
undivided_percent -= Strength;
// and now well do the same stuff for dextery
necessary_minimum = undivided_percent - weaponmax;
if (dexterymin<necessary_minimum)
{
dexterymin = necessary_minimum;
}
if (dexterymax>undivided_percent)
{
dexterymax = undivided_percent;
}
Dextery = Random(dexterymin,dexterymax);
undivided_percent -= Dextery;
// and the last one gets whats left
Weapon = undivided_percent;
Hope you get the idea, I cant guarantee that I did not make a mistake and you can do this prettier (depending on the language your using).
Sorry about frasing my question in an unclear fashion. I forgot to say that I do not know which intervals weapon, strength and dexterity are from. (i.e. I want my solution to be general and not dependent on these intervals).
Because of the different ranges, this is not correct.
For example, if we have the following ranges:
weapon : [1,100]
str: [1,20]
dex: [1,20]
And for example weapon=70, str=20 and dex=9. (i.e. str is maximal)
And let's say the RNG Rf(0,0.2) returns 0.1, Rf(0,0.2) returns 0.1 and Rf(0,0.6) returns 0.3
Then damage is
= 0.1*20 + 0.1*9 + 0.3*70
= 2 + 0.9 + 49 = 51.9
See the problem? The strength component is only 2, which is just about 4% of the total, although strength was at maximum! And the dice wasn't even especially bad (it was average).
However, I was able to find a satisfying solution to the problem.
Let's say the possible range of values in the game is:
wpn: [1, wpn_max]
str: [1, str_max]
dex: [1, dex_max]
i.e. str_max is the maximum strength possible in the game.
And the attacking character has the following values:
wpn = w
str = s
dex = d
Then we define three random variables with uniform distribution:
X_1 = {1,...,w}
X_2 = {1,...,s}
X_3 = {1,...,d}
In the whole game, the maximum for the sum these random variables is:
max = wpn_max + str_max + dex_max
However, the maximum for our specific character is:
total = w + s + d
Our task was to construct a damage function such that "weapon contributes at most 60% of the damage, strength and dexterity both at most 20%, and the damage must be a value from [1, d_max]."
The solution is:
(assuming X_1 = x1, X_2 = x2, and X_3 = x3)
char_damage = (x1)/(w)*0.6*total + (x2)/(s)*0.2*total + (x3)/(e)*0.2*total
final_damage = (char_damage / max) * dmg_max
The idea is not to look at absolute values, but at the "goodness" of each value, i.e. how far away it is from its maximum. First we compute how good the value is for this character, and then how good it is for all possible characters.
It took me several hours to come up with this (I know, I'm stupid), but I did a few tests and it seems to work. I can make it even more general if I replace the percent factors (0.6 etc.) with variables. This is not only useful for damage computation, but for all kinds of RPG character ability checks. The main advantage is that you can formulate RPG rules in an intuitive fashion "lock pick skill determines 80% of the success, and dexterity 20%", and by setting a few variables you already have a complete rule.
Do you think my approach is correct? Can you see any mistakes or problems with this?
Quote:Original post by schattenmaennlein
You want the damage to be 0-20%*Strength + 0-20%*Dextery + 0-60%*Weapon?
Damage = Rf(0,0.2) * Strength + Rf(0,0.2) * Dextery + Rf(0,0.6) * Weapon;
Because of the different ranges, this is not correct.
For example, if we have the following ranges:
weapon : [1,100]
str: [1,20]
dex: [1,20]
And for example weapon=70, str=20 and dex=9. (i.e. str is maximal)
And let's say the RNG Rf(0,0.2) returns 0.1, Rf(0,0.2) returns 0.1 and Rf(0,0.6) returns 0.3
Then damage is
= 0.1*20 + 0.1*9 + 0.3*70
= 2 + 0.9 + 49 = 51.9
See the problem? The strength component is only 2, which is just about 4% of the total, although strength was at maximum! And the dice wasn't even especially bad (it was average).
However, I was able to find a satisfying solution to the problem.
Let's say the possible range of values in the game is:
wpn: [1, wpn_max]
str: [1, str_max]
dex: [1, dex_max]
i.e. str_max is the maximum strength possible in the game.
And the attacking character has the following values:
wpn = w
str = s
dex = d
Then we define three random variables with uniform distribution:
X_1 = {1,...,w}
X_2 = {1,...,s}
X_3 = {1,...,d}
In the whole game, the maximum for the sum these random variables is:
max = wpn_max + str_max + dex_max
However, the maximum for our specific character is:
total = w + s + d
Our task was to construct a damage function such that "weapon contributes at most 60% of the damage, strength and dexterity both at most 20%, and the damage must be a value from [1, d_max]."
The solution is:
(assuming X_1 = x1, X_2 = x2, and X_3 = x3)
char_damage = (x1)/(w)*0.6*total + (x2)/(s)*0.2*total + (x3)/(e)*0.2*total
final_damage = (char_damage / max) * dmg_max
The idea is not to look at absolute values, but at the "goodness" of each value, i.e. how far away it is from its maximum. First we compute how good the value is for this character, and then how good it is for all possible characters.
It took me several hours to come up with this (I know, I'm stupid), but I did a few tests and it seems to work. I can make it even more general if I replace the percent factors (0.6 etc.) with variables. This is not only useful for damage computation, but for all kinds of RPG character ability checks. The main advantage is that you can formulate RPG rules in an intuitive fashion "lock pick skill determines 80% of the success, and dexterity 20%", and by setting a few variables you already have a complete rule.
Do you think my approach is correct? Can you see any mistakes or problems with this?
You probably don't even need to take into account the "ideal" character. You can leave it at this:
dmg_percent = (X1)/(W)*0.6 + (X2)/(S)*0.2 + (X3)/(D)*0.2
final_damage = (1 - dmg_percent)*dmg_min + dmg_percent*dmg_max
dmg_percent = (X1)/(W)*0.6 + (X2)/(S)*0.2 + (X3)/(D)*0.2
final_damage = (1 - dmg_percent)*dmg_min + dmg_percent*dmg_max
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement