Jump to content


How is Sacred 2 Weapon Damage Calculated


Recommended Posts

On the topic of damage conversion. The Temple Guardian's spell Primal Mutation has two entries (modifications) that give damage conversion.

Quote

entry4 = {"et_physical_to_fire", 500, 20, 1, 5 },
entry5 = {"et_physical_to_magic", 500, 20, 2, 5 },

These appear to work as expected, which is explained here https://darkmatters.org/forums/index.php?/topic/18511-how-is-sacred-2-weapon-damage-calculated/&do=findComment&comment=7145649

 

I'll think about adding support for damage conversion entries to the calculator.

Edit: Actually, there is a difference. In the inventory screen and combat art tooltip, the intelligence bonus is correctly applied to the already converted damage. There is no discrepancy between the inventory screen/tooltip and the actual damage dealt, which is generally (but not always) the case with spells.

Edit: Damage conversion, given through a CA entry, works on regular spell damage, essence spell damage and spell damage against a creature type. It does not work on DOT damage.

Entries with the same name are merged together into one, instead of being two separate instances of damage conversion. For example:

Spoiler

{"et_physical_to_fire", 1000, 0, 0, 5 }
{"et_physical_to_fire", 1000, 0, 0, 5 }

The two entries above are merged together into one:

{"et_physical_to_fire", 2000, 0, 0, 5 }

ConversionMultiplier = ValueOfBonus / (ValueOfBonus + 1000)
ConversionMultiplier = 2000 / (2000 + 1000)
ConversionMultiplier = 2000 / 3000
ConversionMultiplier = 0.6666666666666667

 

Edited by Maneus
  • Thanks! 1
Link to comment
 
 

I just read something about a fist fighting character which made me wonder, how much base damage the fists do. So I came over to this thread thinking it's definitely in here somewhere. After searching every page for "unarmed"/"fist" and opening some of the related spoilers etc. I couldn't find anything on this.
I found the info that Fists do have a base damage and that their "weapon level" for attribute bonus calculations is equal to the character level. But even the first tests already get to the base fist damage by subtracting the attribute bonus, meaning without an actual character to look up the attribute bonus and combined damage, there is no way of determining the fist base damage yet.

Did I miss something?
Otherwise it would be another thing to investigate.
We know higher level characters also have higher fist damage, wether that is a direct or indirect(attributes) result. I suspect, that some of the global stuff that also goes into determining how weapons scale with level might have an effect.

And as always, this is just inspiration, I don't really need this info, don't currently plan on making such a character build or anything, so there's absolutely no urgency/priority on figuring this out.
Its just a thing I stumbled upon and was surprised the answer wasn't in here already.

  • Like! 1
Link to comment
 
1 hour ago, SLD said:

I just read something about a fist fighting character which made me wonder, how much base damage the fists do. So I came over to this thread thinking it's definitely in here somewhere. After searching every page for "unarmed"/"fist" and opening some of the related spoilers etc. I couldn't find anything on this.
I found the info that Fists do have a base damage and that their "weapon level" for attribute bonus calculations is equal to the character level. But even the first tests already get to the base fist damage by subtracting the attribute bonus, meaning without an actual character to look up the attribute bonus and combined damage, there is no way of determining the fist base damage yet.

Did I miss something?
Otherwise it would be another thing to investigate.
We know higher level characters also have higher fist damage, wether that is a direct or indirect(attributes) result. I suspect, that some of the global stuff that also goes into determining how weapons scale with level might have an effect.

And as always, this is just inspiration, I don't really need this info, don't currently plan on making such a character build or anything, so there's absolutely no urgency/priority on figuring this out.
Its just a thing I stumbled upon and was surprised the answer wasn't in here already.

For all character classes, except the High Elf:

Fist damage starts at 10 (level 1) and ends at 148 (level 200).

Table:

Spoiler

Level    Damage
1    10
2    10
3    11
4    12
5    12
6    13
7    14
8    14
9    15
10    16
11    17
12    17
13    18
14    19
15    20
16    20
17    21
18    22
19    22
20    23
21    24
22    24
23    25
24    26
25    26
26    27
27    28
28    28
29    29
30    30
31    30
32    31
33    32
34    32
35    33
36    34
37    35
38    35
39    36
40    37
41    38
42    38
43    39
44    40
45    40
46    41
47    42
48    42
49    43
50    44
51    44
52    45
53    46
54    46
55    47
56    48
57    48
58    49
59    50
60    51
61    51
62    52
63    53
64    54
65    54
66    55
67    56
68    56
69    57
70    58
71    58
72    59
73    60
74    60
75    61
76    62
77    62
78    63
79    64
80    64
81    65
82    66
83    67
84    67
85    68
86    69
87    69
88    70
89    71
90    72
91    72
92    73
93    74
94    74
95    75
96    76
97    76
98    77
99    78
100    78
101    79
102    80
103    80
104    81
105    82
106    82
107    83
108    84
109    85
110    85
111    86
112    87
113    88
114    88
115    89
116    90
117    90
118    91
119    92
120    92
121    93
122    94
123    94
124    95
125    96
126    96
127    97
128    98
129    98
130    99
131    100
132    101
133    101
134    102
135    103
136    103
137    104
138    105
139    106
140    106
141    107
142    108
143    108
144    109
145    110
146    110
147    111
148    112
149    112
150    113
151    114
152    114
153    115
154    116
155    116
156    117
157    118
158    119
159    119
160    120
161    121
162    122
163    122
164    123
165    124
166    124
167    125
168    126
169    126
170    127
171    128
172    128
173    129
174    130
175    130
176    131
177    132
178    132
179    133
180    134
181    135
182    135
183    136
184    137
185    137
186    138
187    139
188    140
189    140
190    141
191    142
192    142
193    143
194    144
195    144
196    145
197    146
198    146
199    147
200    148

For the High Elf:

Fist damage starts at 8 (level 1) and ends at 129 (level 200).

I don't have a table.

 

I could not find any parameters that directly affect the fist damage.

  • Like! 1
Link to comment
 
10 hours ago, Maneus said:

I could not find any parameters that directly affect the fist damage.

Wow, that comes as a surprise. Thanks for looking into that anyway.
From the table it looks somewhat like 10 +0.69 per further level, rounded down. So we kinda do have a formula now.
The high elf could be around 12% less for both the base and the scaling again rounded down.

Nice to know, that High Elves are especially bad at fist fighting :)

  • Like! 1
Link to comment
 
 
10 hours ago, Maneus said:

The non-elite demon mage summons a Burning Skeleton at 250 (+10 levels).
The elite demon mage summons a Burning Skeleton at 274 (+34 levels).

I think these exceptions are a result of the summoning combat art just creating creatures at the level that is set in the combat art. So the demons just got a combat art level that usually results in a summon of a slight bit above their level and the elite version got some extra levels on the combat art. In both cases the skeletons are just indirectly influenced via the zone and sb effects as the demons level is the basis for the combat art level.
 

10 hours ago, Maneus said:

This is very odd. I'll think about it some more.

Rest for a bit. The smoke coming out of your ears is not a good sign :)

  • Like! 1
Link to comment
 
17 hours ago, SLD said:

Rest for a bit. The smoke coming out of your ears is not a good sign :)

I could probably power a steam engine :crazy_pilot:

 

The current theory is:

FinalMinCreatureLavel = MOD(BaseMinCreatureLevel + Spawn_OffsetLow, 256)

FinalMaxCreatureLevel = MOD(BaseMaxCreatureLevel + Spawn_OffsetHigh, 256)

TargetCreatureLevel = FLOOR(CharacterLevel * SurvivalBonusMultiplier)

AlmostFinalCreatureLevel = IF(TargetCreatureLevel < FinalMinCreatureLevel, FinalMinCreatureLevel, IF(TargetCreatureLevel > FinalMaxCreatureLevel, FinalMaxCreatureLevel, TargetCreatureLevel))

FinalCreatureLevel = CLAMP(AlmostFinalCreatureLevel, 1, 240)

 

Questions:

Where do BaseMinCreatureLevel and BaseMaxCreatureLevel come from?

How is SurvivalBonusMultiplier calculated? It is a function of the survival bonus (%) and UBspawn_fact, but it is not as simple as multiplying by the value of UBspawn_fact. The results aren't even close.

 

Link to comment
 
1 hour ago, Maneus said:

How is SurvivalBonusMultiplier calculated? It is a function of the survival bonus (%) and UBspawn_fact, but it is not as simple as multiplying by the value of UBspawn_fact. The results aren't even close.

The only really odd idea that I could come up with for this one is that survival bonus isn't a % value, but a giant amount of time. But that would be so absurd to base the formula on that, that I highly doubt I'm helping here :)
Are we sure the bonus is based on the enemy level and not the character level or a combination of both...

Im sorry I can only guess some bs here... I must admit I have not put in the work to understand any of the creature level testing you did above.

The best I can come up with to help with solving this, is giving a specific creature a sufficient max level and then look at the results of 2 or 3 different minlvls slammed with (25,33,50,66,75,100)% SB and a second set with a doubled UBspawn_fact.
Maybe do the same test with different character levels as well.
A lot of game starts, but in the end we got a nice table of results to do our guesswork on.

Please don't let my dumb ideas insult you intelligence. :connie_xmas-moose:

Link to comment
 
 
 
 
9 hours ago, Maneus said:

And SLD is always right on the nose. How does he do it? :inquire:

Well, look at the size of that nose :connie_xmas-moose:

  • Haha 1
Link to comment
 

How is the level difference penalty calculated?

The formula is:

LevelDifferencePenalty = FLOOR3((CharacterLevel + 9) / (CreatureLevel + 9))

Damage = Damage * LevelDifferencePenalty

This LevelDifferencePenalty is only applied when it is less than or equal to 0.850 !

For example, at CharacterLevel 14 and CreatureLevel 18, the LevelDifferencePenalty is equal to 0.851. Since it is above 0.850, then it is not applied.

Spoiler

CharacterLevel = 14
CreatureLevel = 18

LevelDifferencePenalty = FLOOR3((CharacterLevel + 9) / (CreatureLevel + 9))
LevelDifferencePenalty = FLOOR3((14 + 9) / (18 + 9))
LevelDifferencePenalty = FLOOR3(23 / 27)
LevelDifferencePenalty = FLOOR3(0.8518518518518519)
LevelDifferencePenalty = 0.851

You still do the normal damage to the opponent.

But at:

CharacterLevel = 8
CreatureLevel = 11

LevelDifferencePenalty = FLOOR3((CharacterLevel + 9) / (CreatureLevel + 9))
LevelDifferencePenalty = FLOOR3((8 + 9) / (11 + 9))
LevelDifferencePenalty = FLOOR3(17 / 20)
LevelDifferencePenalty = FLOOR3(0.85)
LevelDifferencePenalty = 0.85

If you normally do 10000 damage, then you will do 8500 damage to the opponent.

 

 

How is the level difference bonus calculated?

The formula is:

LevelDifferenceRatio = FLOOR3((LevelDifferencePenalty - (1 + DamScaleRatioMin * 0.001)) / ((DamScaleRatioMax - DamScaleRatioMin) * 0.001))

LevelDifferenceBonus = CLAMP(LevelDifferenceRatio, 0, 1) * DamScaleIncMax * 0.001

Damage = Damage * (1 + LevelDifferenceBonus)

Where:
- DamScaleRatioMin - from balance.txt. Default value is 200.
- DamScaleRatioMax - from balance.txt. Default value is 350.
- DamScaleIncMax - from balance.txt. Default value is 1250.

Example:

Spoiler

CharacterLevel = 100
CreatureLevel = 80
DamScaleRatioMin = 200
DamScaleRatioMax = 350
DamScaleIncMax = 1250
Damage = 10000

LevelDifferencePenalty = FLOOR3((CharacterLevel + 9) / (CreatureLevel + 9))
LevelDifferencePenalty = FLOOR3((100 + 9) / (80 + 9))
LevelDifferencePenalty = FLOOR3(109 / 89)
LevelDifferencePenalty = FLOOR3(1.224719101123596)
LevelDifferencePenalty = 1.224

LevelDifferenceRatio = FLOOR3((LevelDifferencePenalty - (1 + DamScaleRatioMin * 0.001)) / ((DamScaleRatioMax - DamScaleRatioMin) * 0.001))
LevelDifferenceRatio = FLOOR3((1.224 - (1 + 200 * 0.001)) / ((350 - 200) * 0.001))
LevelDifferenceRatio = FLOOR3((1.224 - (1 + 0.2)) / (150 * 0.001))
LevelDifferenceRatio = FLOOR3((1.224 - 1.2) / 0.15)
LevelDifferenceRatio = FLOOR3(0.024 / 0.15)
LevelDifferenceRatio = FLOOR3(0.16)
LevelDifferenceRatio = 0.16

LevelDifferenceBonus = CLAMP(LevelDifferenceRatio, 0, 1) * DamScaleIncMax * 0.001
LevelDifferenceBonus = CLAMP(0.16, 0, 1) * 1250 * 0.001
LevelDifferenceBonus = 0.16 * 1.25
LevelDifferenceBonus = 0.2 (20% bonus damage)

Damage = Damage * (1 + LevelDifferenceBonus)
Damage = 10000 * (1 + 0.2)
Damage = 10000 * 1.2
Damage = 12000 (Reference value is 12000)

 

Edited by Maneus
  • Like! 1
Link to comment
 
On 9/9/2024 at 1:51 AM, SLD said:

I think these exceptions are a result of the summoning combat art just creating creatures at the level that is set in the combat art. So the demons just got a combat art level that usually results in a summon of a slight bit above their level and the elite version got some extra levels on the combat art. In both cases the skeletons are just indirectly influenced via the zone and sb effects as the demons level is the basis for the combat art level.

This appears to be the case.

The elite demon mage in creatures.txt:

Spoiler

mgr.createCreature {
    id = 1392,
    itemtype_id = 610,
    name = "Demon_WL_summoner_elite",
    behaviour = "Enemy_mage",
    dangerclass = 6,
    groupmaxcount = 1,
    elite_creature_id = 1392,
    probabilityforelite = 0.000000,
    rank = 50,
    tenergy_creature_id = 1392,
    template_creature_id = 1790,
    livesremaining = 0,
    unconscioustime = 20,
    palettebits = "1111111111111111",
    monstertype = 1,
    faction_id = 24,
    equipset_id = 448,
    modelscale = 1.100000,
    rise_from_ground = 0,
    has_corpse = 1,
    has_soul = 1,
    can_strafe = 0,
    spells = {
        entry0 = { "enemy_ghost_schock_1" },
        entry1 = { "enemy_spawn_fireskeleton" },
        entry2 = { "enemy_blind" },
    },
}

The template creature:

Spoiler

mgr.createCreature {
    id = 1790,
    itemtype_id = 4828,
    name = "Template_demon_any_elite",
    behaviour = "BoulderDash",
    dangerclass = 0,
    groupmaxcount = 0,
    probabilityforelite = 0.000000,
    rank = 0,
    livesremaining = 0,
    unconscioustime = 20,
    palettebits = "1111111111111111",
    monstertype = 0,
    faction_id = 24,
    modelscale = 1.000000,
    rise_from_ground = 0,
    has_corpse = 1,
    has_soul = 1,
    can_strafe = 0,
}

Both receive a bonus to all CA levels.

Spoiler

mgr.addCreatureBonus( 1392, {
    intensity = 2250,
    bonus = 246,
})

mgr.addCreatureBonus( 1790, {
    intensity = 1320,
    bonus = 246,
})

newBonus = {
--  name = "crbonus_level_CA_all",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_LEVEL_ALL_CA",
  spez = "",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {1,0,0},
  difficultyvaluerange0 = {0,100,4000},
  difficultyvaluerange1 = {1,125,5000},
  difficultyvaluerange2 = {2,150,6000},
  difficultyvaluerange3 = {3,175,7000},
  difficultyvaluerange4 = {4,200,8000},
}
mgr.createBonus(246, newBonus);

The bonuses are calculated separately. The total value is 341.29. This becomes the level of all combat arts. Creatures, as opposed to the playable characters, do not suffer from combat art level penalty.

Spoiler

ValueAt0 = 200
ValueAt200 = 8000
ItemLevel = 240 (It's the creature level)

For the first bonus:

BlueprintMultiplier = 1320

ValueOfBonus = FLOOR((FLOOR(((ValueAt200 - ValueAt0) / 200) * ItemLevel) + ValueAt0) * BlueprintMultiplier * 0.001)
ValueOfBonus = FLOOR((FLOOR(((8000 - 200) / 200) * 240) + 200) * 1320 * 0.001)
ValueOfBonus = FLOOR((FLOOR((7800 / 200) * 240) + 200) * 1.32)
ValueOfBonus = FLOOR((FLOOR(39 * 240) + 200) * 1.32)
ValueOfBonus = FLOOR((FLOOR(9360) + 200) * 1.32)
ValueOfBonus = FLOOR((9360 + 200) * 1.32)
ValueOfBonus = FLOOR(9560 * 1.32)
ValueOfBonus = FLOOR(12619.2)
ValueOfBonus = 12619

CALevelBonus = ValueOfBonus / 100
CALevelBonus = 12619 / 100
CALevelBonus = 126.19

For the second bonus:

BlueprintMultiplier = 2250

ValueOfBonus = FLOOR((FLOOR(((ValueAt200 - ValueAt0) / 200) * ItemLevel) + ValueAt0) * BlueprintMultiplier * 0.001)
ValueOfBonus = FLOOR((FLOOR(((8000 - 200) / 200) * 240) + 200) * 2250 * 0.001)
ValueOfBonus = FLOOR((FLOOR((7800 / 200) * 240) + 200) * 2.25)
ValueOfBonus = FLOOR((FLOOR(39 * 240) + 200) * 2.25)
ValueOfBonus = FLOOR((FLOOR(9360) + 200) * 2.25)
ValueOfBonus = FLOOR((9360 + 200) * 2.25)
ValueOfBonus = FLOOR(9560 * 2.25)
ValueOfBonus = FLOOR(21510)
ValueOfBonus = 21510

CALevelBonus = ValueOfBonus / 100
CALevelBonus = 21510 / 100
CALevelBonus = 215.1

TotalCALevelBonus = 126.19 + 215.1 = 341.29

The combat art in spells.txt:

Spoiler

mgr.defineSpell( "enemy_spawn_fireskeleton", {
    eiStateName = "cSpellCast",
    fxTypeCast = "",
    fxTypeSpell = "FX_GEN_SPAWN1_I",
    duration = 10.000000,
    animType = "ANIM_TYPE_MAGICB",
    animTypeApproach = "",
    animTypeRide = "",
    animTypeSpecial = "",
    causesSpellDamage = 1,
    tokens = {
        entry0 = {"et_summon_officer", 1000, 1234, 0, 8 },
        entry1 = {"et_summon_mylevel", 4, 1, 0, 4 },
    },
    fightDistance = 300.000000,
    aspect = "EA_ENEMY_ANY",
    cooldown = 10.000000,
    soundProfile = 0,
    cost_level = 200,
    cost_base = 400,
    focus_skill_name = "skill__enemy_focus",
    lore_skill_name = "skill__enemy_lore",
    spellClass = "cSpellSpawnEnemy",
    spellcontroltype = "eCAtype_a_effect_location_start",
    sorting_rank = 0,
})

Since the combat art is using the entry et_summon_mylevel, as opposed to et_summon_level, the summoned creature is spawned at the summoner's level plus a bonus from the combat art entry. The bonus in this case is 34, which means that the summoned creature's level is 274.

Spoiler

ValueOfEntry = InitialValue + FLOOR(FinalCombatArtLevel * ValuePerLevel)
ValueOfEntry = 4 + FLOOR(341.29 * 1)
ValueOfEntry = 4 + 341
ValueOfEntry = 345

CreatureLevelBonus = FLOOR(345 / 10)
CreatureLevelBonus = FLOOR(345 / 10)
CreatureLevelBonus = FLOOR(34.5)
CreatureLevelBonus = 34

 

Same thing for the non-elite demon mage. He just has a much lower bonus to CA levels.

 

Edit: The highest possible (summoned) creature level is 65535. At 65536 it overflows and becomes 0, which is then clamped to 1.

Edit2: The difference between et_summon_mylevel and et_summon_level appears to be that et_summon_level uses 80% of the summoner's level as the base. If the summoner is level 100, then the base is 80. If the summoner is level 240, then the base is 192. The bonus to the creature level is calculated in the same way.

BeeEffGee also uses et_summon_level, but in combination with et_summon_item. The summoned item level appears to be capped at 200.

Edited by Maneus
  • Like! 1
Link to comment
 
9 hours ago, Maneus said:

BeeEffGee also uses et_summon_level, but in combination with et_summon_item. The summoned item level appears to be capped at 200.

That cap was added to the game to prevent problems with the items level not just exceeding what your character can currently carry but also what a character ever could carry. I think it previously was capped at 255 which is probably the highest possible item level, but level 255 items would usually require a level 203 character to be equipped.
What problems that actually caused, I don't know.
 

9 hours ago, Maneus said:

Edit: The highest possible (summoned) creature level is 65535. At 65536 it overflows and becomes 0, which is then clamped to 1.

Now I was wondering what possible use could this have. You can't make a mod where the characters can reach these kind of levels and normal monster spawns seem to be capped at level 240, items at 255...
I got it! It's for the "pokemon mod" where every character and monster is immune to damage and they all use summoning combat arts to let their summoned creatures fight each other. In this mod the full summon level range of 65535 could be used. With some kind of mechanic that killed the summoner when all of his creatures are defeated this mod could actually be a thing. Now all we need is for someone to make this mod.
At least you already laid the important scientific groundwork of figuring out the maximum summoned creature level :)
 

9 hours ago, Maneus said:

This appears to be the case.

The size of that nose never disappoints :connie_xmas-moose:

  • Like! 1
Link to comment
 
8 hours ago, SLD said:

I think it previously was capped at 255 which is probably the highest possible item level, but level 255 items would usually require a level 203 character to be equipped.

Yes, the highest possible item level appears to be 255. At 256 it overflows to 0 and is then clamped to 1. And yes, with a level 200 character, I can't equip a level 255 item. Just tested it myself.

8 hours ago, SLD said:

That cap was added to the game to prevent problems with the items level not just exceeding what your character can currently carry but also what a character ever could carry.

You can still summon a level 200 BeeEffGee (item) as a level 1 Seraphim. The weapon appears to be usable.

8 hours ago, SLD said:

The size of that nose never disappoints :connie_xmas-moose:

:lol:

Link to comment
 
1 hour ago, Maneus said:

You can still summon a level 200 BeeEffGee (item) as a level 1 Seraphim. The weapon appears to be usable.

Yes, of course. That's why I said, that I don't know what the actual problem was, that led to the cap at 200. Somehow exceeding what a level 200 character could wear must have caused extra problems. It originally went up to 255 and was capped there to not overflow, so that was not the problem.
 

1 hour ago, Maneus said:

And yes, with a level 200 character, I can't equip a level 255 item. Just tested it myself.

Yes, the formula for that one is known. (20%+1) off. That's how I got to it being supposed to take level 203.(255-[51+1])
It does sometimes not match exactly so I suspect rounding, but I never bothered to test this in detail.
The formula was originally very easy to find as in Sacred 1 they had both Item level and required level shown on the item and the formula there was (20%+2) off, so almost identical.

  • Like! 1
Link to comment
 

How are the hitpoints calculated?

Each character (or creature) has base hitpoints. The base hitpoints are calculated using the following formula:

BaseHitpoints = ((1 + CharacterLevel + LifeStep * 2) * CharacterLevel + LifeBase * 2) * LifeFactor * 0.0001

Where:
- LifeStep - from balance.txt. Default value is 19.
- LifeBase - from balance.txt. Default value is 130.
- LifeFactor - For the playable characters it is 2500. For the creatures it is determined by the parameter LifeFactorDiff which has the following values {1000,1400,2000,3000,4000}, one value for each difficulty level.

In addition to the BaseHitpoints, all characters and creatures receive bonus hitpoints from the vitality attribute.

VitalityHitpoints = (10 / (10 + CharacterLevel)) * Vitality * BaseHitpoints / MAX(LifeAttribut, 1)

Where:
- Vitality - The total vitality value (after Survival Bonus).
- LifeAttribut - from balance.txt. Default value is 25.

TotalHitpoints = MAX(ROUND(BaseHitpoints + VitalityHitpoints + ConstitutionHitpoints), 1)

Where:
- ConstitutionHitpoints - bonus hitpoints from the skill. I'll look into it in another post.

 

The TotalHitpoints appear to be rounded half-up, both in the inventory screen and in practice. If the total is 212.3, then you will see 212. If the total is 342.85, then you will see 343. Very rarely, it is affected by precision loss, which lowers it by 1 point.

The VitalityHitpoints also appear to be rounded half-up, but only in the attribute tooltip and not always. It appears to be more often affected by precision loss and that might be the reason why it seems that it is not always rounded. In practice, when calculating the TotalHitpoints, it is not rounded at all.

Creatures are additionally affected by the parameter MP_lifeHP. The default values are {1000,1300,1650,2100,2650}. This appears to be a multiplier to the TotalHitpoints. It is important to keep in mind, that life leech % is based on the original total. For example:

Spoiler

We have a spell that has 100% leech life from opponents.

Our opponent has 4696.8 hitpoints (before rounding up).

At MP_lifeHP = 1000, the spell does 4697 damage, which kills the opponent in one hit.

At MP_lifeHP = 3000, the spell still does 4697 damage, but it now takes 4 hits to kill the opponent. The first three hits each deal a third of the opponent's hitpoints in damage, but the opponent appears to have at least 1 hitpoint remaining at the end. This appears to happen because the opponent manages to regenerate at least 1 hitpoint before the third hit.

After modifying the spell to have 300% life leech, it now does 14091 damage, which is enough to kill the opponent in one hit.

 

How is hitpoint regeneration calculated?

The formula is:

HitpointsPerSecond = FLOOR(TotalHitpoints / (balanceLifeRegenerationTime * 0.001)) / 10

Where:
- HitpointsPerSecond - the value shown in the inventory screen.
- balanceLifeRegenerationTime - from balance.txt. Default value is 4500.

The skill Constitution does not directly affect the regeneration rate as the tooltip might lead you to believe. It simply raises the TotalHitpoints, which in turn increases the regeneration rate.

 

 

A full example:

Spoiler

Seraphim, level 200
Vitality = 10000
LifeStep = 19
LifeBase = 130
LifeAttribut = 25
LifeFactor = 2500
ConstitutionHitpoints = 0
balanceLifeRegenerationTime = 4500

BaseHitpoints = ((1 + CharacterLevel + LifeStep * 2) * CharacterLevel + LifeBase * 2) * LifeFactor * 0.0001
BaseHitpoints = ((1 + 200 + 19 * 2) * 200 + 130 * 2) * 2500 * 0.0001
BaseHitpoints = ((201 + 38) * 200 + 260) * 0.25
BaseHitpoints = (239 * 200 + 260) * 0.25
BaseHitpoints = (47800 + 260) * 0.25
BaseHitpoints = 48060 * 0.25
BaseHitpoints = 12015

VitalityHitpoints = (10 / (10 + CharacterLevel)) * Vitality * BaseHitpoints / MAX(LifeAttribut, 1)
VitalityHitpoints = (10 / (10 + 200)) * 10000 * 12015 / MAX(25, 1)
VitalityHitpoints = (10 / 210) * 10000 * 12015 / 25
VitalityHitpoints = 0.0476190476190476 * 4806000
VitalityHitpoints = 228857.1428571428 (Reference value is 228856)

TotalHitpoints = MAX(ROUND(BaseHitpoints + VitalityHitpoints + ConstitutionHitpoints), 1)
TotalHitpoints = MAX(ROUND(12015 + 228857.1428571428 + 0), 1)
TotalHitpoints = MAX(ROUND(240872.1428571428), 1)
TotalHitpoints = MAX(240872, 1)
TotalHitpoints = 240872 (Reference value is 240872)

HitpointsPerSecond = FLOOR(TotalHitpoints / (balanceLifeRegenerationTime * 0.001)) / 10
HitpointsPerSecond = FLOOR(240872 / (4500 * 0.001)) / 10
HitpointsPerSecond = FLOOR(240872 / 4.5) / 10
HitpointsPerSecond = FLOOR(53527.11111111111) / 10
HitpointsPerSecond = 53527 / 10
HitpointsPerSecond = 5352.7 (Reference value is 5352.7)

 

Edited by Maneus
  • Like! 1
Link to comment
 
14 hours ago, Maneus said:

The skill Constitution does not directly affect the regeneration rate as the tooltip might lead you to believe. It simply raises the TotalHitpoints, which in turn increases the regeneration rate.

Well it's mastery kinda "increases" the in combat reg... :)

Link to comment
 
 
 

It turns out that the characters' stats, including the fist damage, can be found in creatures.txt.

For example, the High Elf "creature":

Spoiler

mgr.createCreature {
    id = 209,
    itemtype_id = 5,
    name = "SC_Highelve",
    behaviour = "Invalid",
    dangerclass = 7,
    groupmaxcount = 1,
    elite_creature_id = 209,
    probabilityforelite = 0.000000,
    rank = 999,
    tenergy_creature_id = 209,
    livesremaining = 0,
    unconscioustime = 5,
    palettebits = "1111111111111111",
    monstertype = 0,
    faction_id = 1,
    equipset_id = 5,
    modelscale = 1.000000,
    rise_from_ground = 0,
    has_corpse = 1,
    has_soul = 1,
    can_strafe = 0,
    spells = {
        entry0 = { "he_ar_magischerschlag" },
        entry1 = { "he_ar_energieblitz" },
        entry2 = { "he_ar_teleport" },
        entry3 = { "he_ar_regenerationskraft" },
        entry4 = { "he_ar_bannkreis" },
        entry5 = { "he_in_feuerball" },
        entry6 = { "he_in_feuersturm" },
        entry7 = { "he_in_meteor" },
        entry8 = { "he_in_feuerdaemon" },
        entry9 = { "he_in_feuerhaut" },
        entry10 = { "he_st_eissplitter" },
        entry11 = { "he_st_frostschlag" },
        entry12 = { "he_st_schneesturm" },
        entry13 = { "he_st_nebelform" },
        entry14 = { "he_st_kristallhaut" },
    },
}

Receives the following bonuses:

Spoiler

mgr.addCreatureBonus( 209, {
    intensity = 800,
    bonus = 31,--Dexterity
})

mgr.addCreatureBonus( 209, {
    intensity = 1400,
    bonus = 32,--Intelligence
})

mgr.addCreatureBonus( 209, {
    intensity = 1000,
    bonus = 33,--Stamina
})

mgr.addCreatureBonus( 209, {
    intensity = 700,
    bonus = 29,--Strength
})

mgr.addCreatureBonus( 209, {
    intensity = 800,
    bonus = 34,--Vitality
})

mgr.addCreatureBonus( 209, {
    intensity = 1000,
    bonus = 35,--Willpower
})

mgr.addCreatureBonus( 209, {
    intensity = 350,
    bonus = 27,--crbonus_damage_phy
})

mgr.addCreatureBonus( 209, {
    intensity = 2000,
    bonus = 26,--crbonus_experience
})

The attribute bonuses all look like this:

Spoiler

newBonus = {
--  name = "crbonus_attr_dex_pc",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_STATS",
  spez = "STAT_DEX",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {1,0,0},
  difficultyvaluerange0 = {0,23,525},
  difficultyvaluerange1 = {1,23,525},
  difficultyvaluerange2 = {2,23,525},
  difficultyvaluerange3 = {3,23,525},
  difficultyvaluerange4 = {4,23,525},
}
mgr.createBonus(31, newBonus);

They start from 23 (level 0) and go up to 525 (level 200). If the intensity value is 1000, then the attribute will become 525 at level 200. But each character receives the bonuses at different intensity values which is what makes the stats different.

The fist damage bonus:

Spoiler

newBonus = {
--  name = "crbonus_damage_phy",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_WEAPONDAMAGERANGE",
  spez = "DMG_PHYS",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {1,0,0},
  difficultyvaluerange0 = {0,24,371},
  difficultyvaluerange1 = {1,24,371},
  difficultyvaluerange2 = {2,24,371},
  difficultyvaluerange3 = {3,24,371},
  difficultyvaluerange4 = {4,24,371},
}
mgr.createBonus(27, newBonus);

At level 200, that would be 371 damage. The high elf receives this bonus at 350 intensity, which makes the final result 129.85. It is then rounded down to 129.

 

This seems so obvious now. It never occured to me to check the character "creatures"...

Edited by Maneus
  • Like! 1
Link to comment
 

Some findings about Energy Shields

Any character can receive an Energy Shield through the bonus type "BONUS_SHIELD". There are two bonuses in blueprint.txt that have it:

Spoiler

newBonus = {
--  name = "bb_shieldstrength",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_SHIELD",
  spez = "",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {0,0,0},
  difficultyvaluerange0 = {0,0,0},
  difficultyvaluerange1 = {1,0,0},
  difficultyvaluerange2 = {2,0,0},
  difficultyvaluerange3 = {3,0,0},
  difficultyvaluerange4 = {4,0,0},
}
mgr.createBonus(409, newBonus);

newBonus = {
--  name = "XXXsb_esldl_eshield_strength",
  rating = 16,
  basedonskill = "skill_energy_shield_lore",
  type = "BONUS_SHIELD",
  spez = "",
  spez2 = "",
  usagebits = 65505,
  minconstraints = {1,5,0},
  difficultyvaluerange0 = {0,20,100},
  difficultyvaluerange1 = {1,30,150},
  difficultyvaluerange2 = {2,40,200},
  difficultyvaluerange3 = {3,50,250},
  difficultyvaluerange4 = {4,60,300},
}
mgr.createBonus(517, newBonus);

The second one appears to be based on the skill Warding Energy Lore, so it probably won't do anything by itself. And the first one has 0 for its values, because they are set by the combat art entries. But if you define a new bonus like so:

Spoiler

newBonus = {
--  name = "bb_shieldstrength2",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_SHIELD",
  spez = "",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {0,0,0},
  difficultyvaluerange0 = {0,1000,1000},
  difficultyvaluerange1 = {1,1000,1000},
  difficultyvaluerange2 = {2,1000,1000},
  difficultyvaluerange3 = {3,1000,1000},
  difficultyvaluerange4 = {4,1000,1000},
}
mgr.createBonus(20005, newBonus);

And give it to a creature or item, then it works. Note: Don't copy-paste code from this site as there is an issue with the symbol encodings. Instead, copy an existing bonus in blueprint.txt and modify it.

The value of the bonus isn't a flat amount, but a percentage. The hitpoints of the Energy Shield appear to be based on the character's BaseHitpoints. So a bonus value of 1000 means 100% of the BaseHitpoints. If your character has BaseHitpoints of 12015, then the Energy Shield will also be 12015. If you give this bonus to an item, then the item tooltip will show Max. shield energy +100.0%. Multiple bonuses of this type stack additively.

The attribute Willpower increases the energy shield hitpoints just like Vitality increases the regular hitpoints. The formula is the same.

While the TotalHitpoints are rounded half-up, the TotalEnergyShieldHitpoints appear to be rounded down.

So far, this means that energy shield hitpoints and regular hitpoints share a lot of the parameters from balance.txt. But there are also:

Quote

balanceShieldRegDelayCombatFactor = 500,
balanceShieldRegDelayDangerFactor = 2,
balanceShieldRegTime = 2000,
balanceShieldAbsorptionSkill = 50,

The Energy Shield regenerates at a much faster rate, and the reason is the much lower value of balanceShieldRegTime (2000) compared to balanceLifeRegenerationTime (4500).

 

There is also the bonus type "BONUS_SHIELD_REL", which seems like percentage increase to the base "BONUS_SHIELD". WIll have to do some tests.

 

Energy Shields have the property Absorption Warding Energy, which is the percentage of damage that is diverted to the energy shield hitpoints. The blueprint bonus type is "BONUS_SHIELDFACTOR". If the character does not have such a bonus, then the Absorption Warding Energy will be 50%. The first instance of this bonus sets the value - it won't stack with the default value, but rather override it. That is why all energy shield combat arts explicitly set it via a combat art entry. Additional instances of this bonus will stack additively.

There are also "BONUS_SHIELDFACTOR_IGNORE" and "BONUS_SHIELDFACTOR_IGNORE_POTENTIAL" which I'll look into later.

 

Energy Shields can also block a flat amount of damage. The bonus type is "BONUS_SHIELDBLOCK". If the character does not have such a bonus, then no damage will be blocked. WIll have to see where does it fit in the overall damage formula.

 

The bonus type "BONUS_SHIELD_REGENERATION" represents flat regeneration rate, which works in and out of combat (just like regular flat hitpoint regeneration). That is what the Temple Guardian uses (the modification of the combat art). I think it was affected by the Tactics Lore/Aspect Lore skill, but I will have to check this. I suspect that the Aspect Lore skill only affects bonuses that come from a combat art, and not when given directly to a creature or item.

The bonus type "BONUS_SHIELD_RELOAD_REL" seems to be a percentage bonus to the regeneration rate. I wonder how (or if) it interacts with the flat regeneration bonus.

 

 

So many things to test... :moil:

 

Note: The graphical effect - the blue field of hexagons around the character - comes from the combat arts (buffs).

Edited by Maneus
  • Like! 1
Link to comment
 

While browsing through the character "creatures", I noticed that some of them receive an additional hidden bonus.

For example, the Temple Guardian:

Spoiler

mgr.createCreature {
    id = 210,
    itemtype_id = 6,
    name = "SC_Templeguardian",
    behaviour = "Invalid",
    dangerclass = 7,
    groupmaxcount = 1,
    elite_creature_id = 210,
    probabilityforelite = 0.000000,
    rank = 999,
    tenergy_creature_id = 210,
    livesremaining = 0,
    unconscioustime = 5,
    palettebits = "1111111111111111",
    monstertype = 0,
    faction_id = 1,
    modelscale = 1.000000,
    rise_from_ground = 0,
    has_corpse = 1,
    has_soul = 1,
    can_strafe = 0,
    spells = {
        entry0 = { "tw_cc_kampfarm" },
        entry1 = { "tw_cc_todesspiesse" },
        entry2 = { "tw_cc_schoepfungsschlag" },
        entry3 = { "tw_cc_kampfaura" },
        entry4 = { "tw_cc_tkampfschild" },
        entry5 = { "tw_te_projektil" },
        entry6 = { "tw_te_flammenwerfer" },
        entry7 = { "tw_te_archimedisstrahl" },
        entry8 = { "tw_te_tschock" },
        entry9 = { "tw_te_levitieren" },
        entry10 = { "tw_en_mutieren" },
        entry11 = { "tw_en_energienetz" },
        entry12 = { "tw_en_gluthitze" },
        entry13 = { "tw_en_eiseskaelte" },
        entry14 = { "tw_en_schockpulse" },
        entry15 = { "tw_cc_kampfaura_buff" },
    },
}

Receives:

Spoiler

mgr.addCreatureBonus( 210, {
    intensity = 960,
    bonus = 31,--crbonus_attr_dex_pc
})

mgr.addCreatureBonus( 210, {
    intensity = 1040,
    bonus = 32,--crbonus_attr_int_pc
})

mgr.addCreatureBonus( 210, {
    intensity = 1000,
    bonus = 33,--crbonus_attr_sta_pc
})

mgr.addCreatureBonus( 210, {
    intensity = 1080,
    bonus = 29,--crbonus_attr_str_pc
})

mgr.addCreatureBonus( 210, {
    intensity = 900,
    bonus = 34,--crbonus_attr_vit_pc
})

mgr.addCreatureBonus( 210, {
    intensity = 1000,
    bonus = 35,--crbonus_attr_wil_pc
})

mgr.addCreatureBonus( 210, {
    intensity = 200,
    bonus = 423,--crbonus_block_stun
})

mgr.addCreatureBonus( 210, {
    intensity = 400,
    bonus = 27,--crbonus_damage_phy
})

mgr.addCreatureBonus( 210, {
    intensity = 2000,
    bonus = 26,--crbonus_experience
})

In particular, this one:

Quote

mgr.addCreatureBonus( 210, {
    intensity = 200,
    bonus = 423,--crbonus_block_stun
})

Spoiler

newBonus = {
--  name = "crbonus_block_stun",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_CHANCE_BLOCKDAMAGE",
  spez = "BLOCK_STUN",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {0,0,0},
  difficultyvaluerange0 = {0,500,500},
  difficultyvaluerange1 = {1,600,600},
  difficultyvaluerange2 = {2,700,700},
  difficultyvaluerange3 = {3,850,850},
  difficultyvaluerange4 = {4,1000,1000},
}
mgr.createBonus(423, newBonus);

I gave this bonus to an item (niobium difficulty; item level 200; at the same intensity value) and the item tooltip shows Block Chance: Stun +18.7%.

 

The Seraphim:

Spoiler

mgr.createCreature {
    id = 1,
    itemtype_id = 1,
    name = "SC_Seraphim",
    behaviour = "Invalid",
    dangerclass = 7,
    groupmaxcount = 1,
    elite_creature_id = 1,
    probabilityforelite = 0.000000,
    rank = 999,
    tenergy_creature_id = 1,
    livesremaining = 0,
    unconscioustime = 5,
    palettebits = "1111111111111111",
    monstertype = 0,
    faction_id = 1,
    equipset_id = 2,
    modelscale = 1.000000,
    rise_from_ground = 0,
    has_corpse = 1,
    has_soul = 1,
    can_strafe = 0,
    spells = {
        entry0 = { "se_co_schlaghagel" },
        entry1 = { "se_co_wirbelsprung" },
        entry2 = { "se_co_seelenhammer" },
        entry3 = { "se_co_befluegeln" },
        entry4 = { "se_co_kampfhaltung" },
        entry5 = { "se_cm_lichtsaeule" },
        entry6 = { "se_cm_lichtaura" },
        entry7 = { "se_cm_bekehrung" },
        entry8 = { "se_cm_blitz" },
        entry9 = { "se_cm_heilen" },
        entry10 = { "se_te_energieschild" },
        entry11 = { "se_te_beeeffgee" },
        entry12 = { "se_te_notschild" },
        entry13 = { "se_te_schwertfeuer" },
        entry14 = { "se_te_schockwelle" },
    },
}

Receives:

Spoiler

mgr.addCreatureBonus( 1, {
    intensity = 150,
    bonus = 256,--crbonus_addAW
})

mgr.addCreatureBonus( 1, {
    intensity = 1040,
    bonus = 31,--crbonus_attr_dex_pc
})

mgr.addCreatureBonus( 1, {
    intensity = 1000,
    bonus = 32,--crbonus_attr_int_pc
})

mgr.addCreatureBonus( 1, {
    intensity = 1000,
    bonus = 33,--crbonus_attr_sta_pc
})

mgr.addCreatureBonus( 1, {
    intensity = 900,
    bonus = 29,--crbonus_attr_str_pc
})

mgr.addCreatureBonus( 1, {
    intensity = 1000,
    bonus = 34,--crbonus_attr_vit_pc
})

mgr.addCreatureBonus( 1, {
    intensity = 1060,
    bonus = 35,--crbonus_attr_wil_pc
})

mgr.addCreatureBonus( 1, {
    intensity = 400,
    bonus = 27,--crbonus_damage_phy
})

mgr.addCreatureBonus( 1, {
    intensity = 1000,
    bonus = 26,--crbonus_experience
})

In particular, this one:

Quote

mgr.addCreatureBonus( 1, {
    intensity = 150,
    bonus = 256,--crbonus_addAW
})

Spoiler

newBonus = {
--  name = "crbonus_addAW",
  rating = 0,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_COMBATVALUE",
  spez = "CBTVAL_ATTACK",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {1,0,0},
  difficultyvaluerange0 = {0,23,525},
  difficultyvaluerange1 = {1,32,700},
  difficultyvaluerange2 = {2,41,875},
  difficultyvaluerange3 = {3,50,1050},
  difficultyvaluerange4 = {4,62,1300},
}
mgr.createBonus(256, newBonus);

I gave this bonus to an item (niobium difficulty; item level 200; at the same intensity value) and the item tooltip shows Attack Value +195.

 

The Shadow Warrior:

Spoiler

mgr.createCreature {
    id = 93,
    itemtype_id = 3,
    name = "SC_Schattenkrieger",
    behaviour = "Invalid",
    dangerclass = 7,
    groupmaxcount = 1,
    elite_creature_id = 93,
    probabilityforelite = 0.000000,
    rank = 999,
    tenergy_creature_id = 93,
    livesremaining = 0,
    unconscioustime = 5,
    palettebits = "1111111111111111",
    monstertype = 0,
    faction_id = 1,
    equipset_id = 1,
    modelscale = 1.000000,
    rise_from_ground = 0,
    has_corpse = 1,
    has_soul = 1,
    can_strafe = 0,
    spells = {
        entry0 = { "sk_hc_harterschlag" },
        entry1 = { "sk_hc_befreiungsschlag" },
        entry2 = { "sk_hc_rammstoss" },
        entry3 = { "sk_hc_kampfruf" },
        entry4 = { "sk_hc_willensstaerke" },
        entry5 = { "sk_tc_attacke" },
        entry6 = { "sk_tc_sprung" },
        entry7 = { "sk_tc_standarte" },
        entry8 = { "sk_tc_kampfrausch" },
        entry9 = { "sk_tc_umlenkung" },
        entry10 = { "sk_ap_geisterhand" },
        entry11 = { "sk_ap_unterstuetzung" },
        entry12 = { "sk_ap_kampfbefehl" },
        entry13 = { "sk_ap_geistform" },
        entry14 = { "sk_ap_kohorte" },
        entry15 = { "sk_ap_geistform_buff" },
    },
}

Receives:

Spoiler

mgr.addCreatureBonus( 93, {
    intensity = 840,
    bonus = 31,--crbonus_attr_dex_pc
})

mgr.addCreatureBonus( 93, {
    intensity = 880,
    bonus = 32,--crbonus_attr_int_pc
})

mgr.addCreatureBonus( 93, {
    intensity = 1040,
    bonus = 33,--crbonus_attr_sta_pc
})

mgr.addCreatureBonus( 93, {
    intensity = 1080,
    bonus = 29,--crbonus_attr_str_pc
})

mgr.addCreatureBonus( 93, {
    intensity = 1120,
    bonus = 34,--crbonus_attr_vit_pc
})

mgr.addCreatureBonus( 93, {
    intensity = 1040,
    bonus = 35,--crbonus_attr_wil_pc
})

mgr.addCreatureBonus( 93, {
    intensity = 400,
    bonus = 27,--crbonus_damage_phy
})

mgr.addCreatureBonus( 93, {
    intensity = 100,
    bonus = 51,--crbonus_damping_poi
})

mgr.addCreatureBonus( 93, {
    intensity = 2000,
    bonus = 26,--crbonus_experience
})

In particular, this one:

Quote

mgr.addCreatureBonus( 93, {
    intensity = 100,
    bonus = 51,--crbonus_damping_poi
})

Spoiler

newBonus = {
--  name = "crbonus_damping_poi",
  rating = 2,
  basedonskill = "SKILL_INVALID",
  type = "BONUS_DAMPING",
  spez = "DMG_POISON",
  spez2 = "",
  usagebits = 65535,
  minconstraints = {0,0,0},
  difficultyvaluerange0 = {0,500,500},
  difficultyvaluerange1 = {1,600,600},
  difficultyvaluerange2 = {2,700,700},
  difficultyvaluerange3 = {3,850,850},
  difficultyvaluerange4 = {4,1000,1000},
}
mgr.createBonus(51, newBonus);

I gave this bonus to an item (niobium difficulty; item level 200; at the same intensity value) and the item tooltip shows Damage mitigation: Poison +10.0%.

 

Obviously, the value of the bonus depends on the character level and difficulty.

 

Edit: The formula for Block Chance: Stun appears to be:

BlockChanceStun = (ValueOfBonus + 32) / (ValueOfBonus + 1032)

In the tooltip, the shown percentage is affected by precision loss from 32-bit floats.

Edited by Maneus
  • Like! 1
Link to comment
 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...