Page 2 of 3

Re: Damage formula

PostPosted: 26 Jan 2015, 15:58
by Esthlos
(H) :D :wink: :P
Gj Esthlos, is there value for directions?
Direction modifier for melee attacks (ranged attacks always get a x1 modifier):
DirMod
Formula:
Formula
P.S. For ease of use, I'm moving the units' stats in this post :P
("+Bows Def" also applies against the rocks thrown by Rogues)
Data
These values all refer to r6720

Re: Damage formula

PostPosted: 26 Jan 2015, 21:00
by RandomLyrics
Nice work, thanks :)

Re: Damage formula

PostPosted: 02 Mar 2015, 13:35
by Xfuryion
  Code:
//Base damage is the unit attack strength + AttackHorse if the enemy is mounted Damage := gRes.UnitDat[fUnit.UnitType].Attack; if (fOpponent.UnitType in [low(UnitGroups) .. high(UnitGroups)]) and (UnitGroups[fOpponent.UnitType] = gt_Mounted) then Damage := Damage + gRes.UnitDat[fUnit.UnitType].AttackHorse; Damage := Damage * (GetDirModifier(fUnit.Direction,fOpponent.Direction)+1); //Direction modifier //Defence modifier Damage := Damage div Math.max(gRes.UnitDat[fOpponent.UnitType].Defence, 1); //Not needed, but animals have 0 defence IsHit := (Damage >= KaMRandom(101)); //Damage is a % chance to hit if IsHit then fOpponent.HitPointsDecrease(1, fUnit);
Translation:
The damage variable is the Attack of the unit (see the chart above for the correct number)
Next it checks if the enemy unit is mounted, if so it adds the modifier of AttackHorse.
Then it takes in consideration the direction
Finally it divides the damage with the defence modifier.

Now it checks with a RNG if there is a hit. If this is the case it decreases the unit's health by 1.

For example:
We have a Militia and a Knight fighting. The Militia looks south and the Knight looks north.

Militia:
Health: 2
Attack: 35
Horse: 0
Defence: 1

Knight:
Health: 4
Attack: 55
Horse: 0
Defence: 3

The damage formula for the Militia:
Damage = Attack = 35
Damage = Damage+AttackHorse = 35+0
Damage = Damage*Direction modifier = 35*1
Damage = Damage/Defence Knight = 35/3
Damage = 11,6

The damage formula for the Knight:
Damage = Attack = 55
Damage = Damage+AttackHorse = 55+0
Damage = Damage*Direction modifier = 55*1
Damage = Damage/Defence Militia = 55/1
Damage = 55

So the Militia it's damage is 11,6 and the Knight's damage is 55. I guess that KamRandom just generates a number between 0 and 101.
So if on a hit the Militia's damage (11,6) is higher than the generated number say for example 10, the Knight gets -1 hitpoint so it has 3 health left.

Practically the Knight will win but in theory the Militia can win aswell. It all depends on RNG/luck. But as you can see, the Knight has a significant higher chance to win. Hopefully this helps you guys.

If my interpretation of the formula is wrong, please correct me.

Re: Damage formula

PostPosted: 02 Mar 2015, 18:32
by Ben
Image
These values all refer to r6720
Are you sure this is right? Because I know scouts have the same LoS as other units (no longer 18). Also I think they moved xbow defense back to .50?

Re: Damage formula

PostPosted: 02 Mar 2015, 20:15
by Esthlos
Are you sure this is right? Because I know scouts have the same LoS as other units (no longer 18). Also I think they moved xbow defense back to .50?
Absolutely.

I modded in a function called States.aPrintValues with the exact intent of retrieving that data, which used the same code the damage formulae use and printed it in the log file; this was done with the code downloaded with TortoiseSVN following the instructions in the wiki to download the latest source code. (H) :wink: :P

Re: Damage formula

PostPosted: 02 Mar 2015, 20:33
by Ben
Well scouts don't have 18 line of sight.

Re: Damage formula

PostPosted: 02 Mar 2015, 20:54
by Esthlos
Well scouts don't have 18 line of sight.
It is what gRes.UnitDat[ut_HorseScout].Sight returns. :|

EDIT: A quick test with the map editor confirmed that the Scout's sight range is indeed double that of the other warrior types in the downloaded source code; its stated version in the loader is r6720.

EDIT2: But it is not in the official r6720. :?

EDIT3: All right, the modded executable works with the official r6720 files... rebuilding the table now.

Re: Damage formula

PostPosted: 02 Mar 2015, 21:41
by Esthlos
Here, copied the modded KaM_Remake.exe and redid the table; same procedure as the last time.

It looks like the Scout's line of sight was the only wrong value.
Table
EDIT: Just to be complete, here's the code used.
This is the added function:
  Code:
function TKMScriptStates.aaaGetData(aUnitType: Integer): String; var aString: String; var aaaType: TUnitType; begin aaaType := UnitIndexToType[aUnitType]; aString := 'Type: '+IntToStr(aUnitType)+'; '; aString := aString+' Health: '+IntToStr(gRes.UnitDat[aaaType].HitPoints)+'; '; aString := aString+' Attack: '+IntToStr(gRes.UnitDat[aaaType].Attack)+'; '; aString := aString+' AttackHorse: '+IntToStr(gRes.UnitDat[aaaType].AttackHorse)+'; '; aString := aString+' Defence: '+IntToStr(gRes.UnitDat[aaaType].Defence)+'; '; aString := aString+' CrossBowsDef: '+FloatToStr(gRes.UnitDat[aaaType].GetDefenceVsProjectiles(True))+'; '; aString := aString+' BowsDef: '+FloatToStr(gRes.UnitDat[aaaType].GetDefenceVsProjectiles(False))+'; '; aString := aString+' Sight: '+IntToStr(gRes.UnitDat[aaaType].Sight)+'; '; result := aString; end;
And this is the code in the mission script
  Code:
function aName(aType: Integer): String; begin case aType of 0: result := 'Serf '; 1: result := 'Woodcutter '; 2: result := 'Miner '; 3: result := 'Animal Breeder '; 4: result := 'Farmer '; 5: result := 'Carpenter '; 6: result := 'Baker '; 7: result := 'Butcher '; 8: result := 'Fisherman '; 9: result := 'Laborer '; 10: result := 'Stone Mason '; 11: result := 'Blacksmith '; 12: result := 'Metallurgist '; 13: result := 'Recruit '; 14: result := 'Militia '; 15: result := 'Axe Fighter '; 16: result := 'Sword Fighter '; 17: result := 'Bowman '; 18: result := 'Crossbowman '; 19: result := 'Lance Carrier'; 20: result := 'Pikeman '; 21: result := 'Scout '; 22: result := 'Knight '; 23: result := 'Barbarian '; 24: result := 'Rebel '; 25: result := 'Rogue '; 26: result := 'Warrior '; 27: result := 'Vagabond '; end; end; procedure OnBeacon(aPlayerIndex: Integer; aX: Integer; aY: Integer); var i: Integer; begin for i := 0 to 27 do Actions.Log(aName(i)+': '+States.aaaGetData(i)); end;
Then the output in the log file was elaborated with LibreOffice Calc, copied in GIMP and exported as a jpg file, which has then been attached to the post.

Re: Damage formula

PostPosted: 06 Apr 2015, 13:28
by Soldado con espada
Great thread, I wanted to understand how the fighting system worked :)

Esthlos, do you think that you could add the "Attack speed" to the table, to make it totally complete?
I know that archers attack faster than crossbowmen (and even faster in KaM Remake), but how much faster? What about infantry, cavalry, etc?

(I haven't been able to find it with the search function.)

Thank you!

Edit: by the way, I see this is in the Original KaM subforum. But these stats are for remake, right?
Also, another question, just to be sure: Xbow = crossbow? :)

Re: Damage formula

PostPosted: 06 Apr 2015, 14:21
by equalizer
an X can also be referred to as a Cross :P

Re: Damage formula

PostPosted: 06 Apr 2015, 19:41
by Esthlos
Esthlos, do you think that you could add the "Attack speed" to the table, to make it totally complete?
I know that archers attack faster than crossbowmen (and even faster in KaM Remake), but how much faster? What about infantry, cavalry, etc?
As far as I know, the maximum attack speed is approximatively 2 attacks per second for melee warriors and Bowmen, and 1 per second for Crossbowmen.

Keep in mind though that this stat is highly influenced by randomness, so results vary a lot.

The code keeps track of this using a "delay between attacks" system, with values:
5+(0<>3) ticks for melee units;
4+(0<>4) ticks for Bowmen;
8+(0<>8) ticks for Crossbowmen;
12 ticks for Rogues.

"(0<>3)" stands for "a random number between 0 and 3".
A "tick" is 1/10 of a second.

EDIT: Also, since these are relevant and were just above the attack delay values:

HP healed: 1 every 100 ticks for every living unit;
Ranged units range: 4 tiles min, 10.99 tiles max;
Watchtower range: 0 tiles min, 6.99 tiles max (from the doorway);
But these stats are for remake, right?
They are, but it should apply pretty well to the original game as well; the Remake strives to be very close to the old KaM gameplay-wise, while improving it from a technical and quality-of-life point of view.
There was no "shield bonus" against ranged attacks in the original, though.

Re: Damage formula

PostPosted: 07 Apr 2015, 12:07
by Esthlos
Don't know where else to put this, but since I already have done the math I think it's worth it to post it here...
Approximately if the cost ratio is lower than the hit chance ratio, then the most cost/effective warrior in the comparison should (there are other factors which have not been taken in consideration) be the one at the numerator.

Axes vs Swords
Ratio (Knights' cost in Corn)/(Scouts' cost in Corn)=1,3889
Ratio (Sword Fighters' cost in Corn)/(Axe Fighters' cost in Corn)=1,6087
Ratio (Swords' chance of wounding <Target>)/(Axes' chance of wounding <Target>), frontally=
1,5714 vs anyone

Lances vs Pikes
Ratio (Pikemen's cost in Corn)/(Lance Carriers' cost in Corn)=1,3684
Ratio (Pikemen's chance of wounding <Target>)/(Lance Carriers' chance of wounding <Target>), frontally=
1,4375 vs Mounted units
1,4000 vs anyone else

Crossbows vs Bows
Ratio (Crossbowmen cost in Corn)/(Bowmen cost in Corn)=1,3684
Ratio (Crossbowmen's chance of wounding <Target>)/(Bowmen's chance of wounding <Target>), in the time needed for 1 bolt to be thrown=
1,4286 vs Civilians, Militia, Rebels, Rogues, Vagabonds
1,4814 vs Axe Fighters, Scouts
1,3306 vs Sword Fighters, Knights
1,1765 vs Bowmen, Lance Carriers, Barbarians, Warriors
1,1111 vs Crossbowmen, Pikemen

Lances vs Axes
Ratio (Scouts' cost in Corn)/(Lance Carriers' cost in Corn)=1,8947
Ratio (Axe Fighter's cost in Corn)/(Lance Carriers' cost in Corn)=1,2105
Ratio (Axes' chance of wounding <Target>)/(Lances' chance of wounding <Target>), frontally=
0,4375 vs Mounted units
1,4000 vs anyone else

Pikes vs Swords
Ratio (Knights' cost in Corn)/(Pikemen's cost in Corn)=1,9230
Ratio (Sword Fighter's cost in Corn)/(Pikemen's cost in Corn)=1,4231
Ratio (Swords' chance of wounding <Target>)/(Pikes' chance of wounding <Target>), frontally=
0,4783 vs Mounted units
1,5714 vs anyone else

Re: Damage formula

PostPosted: 08 Apr 2015, 00:11
by Soldado con espada
Thanks a lot for your reply, I thought the attack speed was a constant, this game has many surprises :D


I'm not understanding what is the "corn equivalent" that you are using. At the beginning I thought it would be actual "corn" (I don't play the game in English, and it hurts calling it with the wrong name xD), but of course I don't spend "corn" in making iron weapons.

Edit: I saw in another post of yours that you are using "market values". A bit of a rough estimate in my opinion, but I have no idea how to do it better :)

Re: Damage formula

PostPosted: 08 Apr 2015, 05:43
by Krom
Actual unit costs are tricky to calculate, because of too many factors involved. I'll try to list in order of importance:
  • armament/weapon production time,
  • production cost in steel/coal and other source wares,
  • initial production chain cost (wares required to build Farms/Mines, hire citizens),
  • production delay (time it takes to get it all running),
  • production chain running cost (hiring serfs to transport it all, feeding units involved),
  • amount of space that production chain needs,
  • specific maps resources availability,
  • other factors I could have forgot
Market cost includes only the most significant of those.

P.S. Put aside Market costs origin, it makes little sense to use Corn prices (which have inherent ~5% error in them) and calculate ratios with 4 digits after the decimal delimiter.

Re: Damage formula

PostPosted: 08 Apr 2015, 06:47
by Esthlos
Edit: I saw in another post of yours that you are using "market values". A bit of a rough estimate in my opinion, but I have no idea how to do it better :)
Neither do I :P
[...]
Yes, I believe I wrote it in the first three lines that there is a significant imprecision in the ratios, and that these results should not be taken as literal truths... :P

Another factor which matters but has not been taken in consideration is the numerical advantage of cheaper units: since they are more numerous than costier ones, their total HP pool is larger and their chance of flanking their target (given enough space on the battlefield) is higher; both factors impact signifiantly on the effectiveness of the units, but are I fear very hard to estimate.

(Putting 4 decimal digits is a completely arbitrary decision of course: I'm working with tools whose precision I do not properly know, so I couldn't use that to determine the appropriate number of decimals :$ )