User:Sheepy: Difference between revisions

From Heroes of Hammerwatch Wiki
Jump to navigation Jump to search
Sheepy (talk | contribs)
Added investigation results for enemy scaling
Sheepy (talk | contribs)
Re-worded elixir explanation
 
(23 intermediate revisions by the same user not shown)
Line 6: Line 6:


If you're >10 levels below the area:
If you're >10 levels below the area:
xpMul=1.0+(5−lvlDiff)x0.15
xpMul=1.0+(lvlDiff+10)x0.15


{| class="wikitable"
{| class="wikitable"
Line 26: Line 26:


If you're >5 levels above the area:
If you're >5 levels above the area:
xpMul=1.0+(lvlDiff+10)x0.15
xpMul=1.0+(5−lvlDiff)x0.15
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 45: Line 45:


'''Source''': PlayerRecord.as - int GiveExperience(int amount, bool skipGainMod = false)
'''Source''': PlayerRecord.as - int GiveExperience(int amount, bool skipGainMod = false)
=== Multiplayer exp ===
Exp is divided equally between players before going through the exp penalty formula.
'''Source''': GiveExperience.as - bool Apply(Actor@ owner, UnitPtr target, vec2 pos, vec2 dir, float intensity, bool husk)


== Architect Modifiers ==
== Architect Modifiers ==
Line 61: Line 55:


With Treasure Hunt: ( 1 - ( 0.92 ^ 12 ) ) x 100 = 63.23% chance of seeing the treasury on a full run
With Treasure Hunt: ( 1 - ( 0.92 ^ 12 ) ) x 100 = 63.23% chance of seeing the treasury on a full run
Addendum: it is not guaranteed that the map generation succeeds in placing the treasury. More investigation required here.


'''Source''': themes_dungeon.sval, themes_barracks.sval, themes_courts.sval - search for "treasury"
'''Source''': themes_dungeon.sval, themes_barracks.sval, themes_courts.sval - search for "treasury"
=== Righteous Flames ===
Applicable to Dungeon, Barracks and Courts. Appears to enable an extra Pyre prefab to the regular list of prefabs, unsure how much likelier this makes Pyres to appear. Needs investigation into level generation to understand the impact.
=== Weak Defenses ===
Reduces enemy density by 25%.
m_missionLevel.m_generator.m_enemyPlacer.m_densityMul *= 0.75f;
'''Source''': MissionGameMode.as - void Start(uint8 peer, SValue@ save, StartMode sMode) override
=== Poor Training ===
50% chance to disable allowing Elite generation, for each enemy.
m_missionLevel.m_generator.m_enemyPlacer.m_allowElites = randf() < 0.5f;
'''Source''': MissionGameMode.as - void Start(uint8 peer, SValue@ save, StartMode sMode) override


== Scaling ==
== Scaling ==


=== Enemy HP ===
=== Enemy HP ===
Simplified: hp = ( base_hp + ngp_level x 25 ) x ( 1 + mp_scaling + ngp_level x 2.75 )
hp = ( base_hp + ng_level x 25 ) x ( 1 + mp_scaling x enemy_mp_scaling ) x ( 1 + enemy_ng_scaling x ng_level x 2.75 )  


Note that mp_scaling will vary depending on the enemy, value of 1 for Avatar in solo.
mp_scaling = (player_count - 1) x player_count ^ 0.35 + max(0, (player_count - 2) x 0.3f);
 
mp_scaling = 0 in solo
 
enemy_mp_scaling = 1
 
enemy_ng_scaling = 1 for everything except forest enemies at 0.5


The following table is for Avatar's 100k base hp
The following table is for Avatar's 100k base hp
Line 107: Line 129:
|2,857,125.00
|2,857,125.00
|}
|}
'''Source''': CompositeActorBehavior.as - GetMaxHp()
=== Multiplayer ===
Enemy HP is increased in multiplayer with the following code:
g_mpEnemyHealthScale = (num - 1) * pow(num, -0.35) + max(0.0f, (num - 2) * 0.3f);
Which is then used as part of the hp calculation:
float ret = m_props.m_maxHp + (m_props.m_ngpScale * g_ngp * 25);
ret *= (1.0f + g_mpEnemyHealthScale * m_props.m_mpScaleFact) * Tweak::EnemyHealthMul;
'''''m_props.mpScaleFact varies per enemy'''''
'''Source''':  
'''Source''':  
 
CompositeActorBehavior.as - GetMaxHp()
AGameplayGameMode.as - RefreshMultiplayerScaling()
AGameplayGameMode.as - RefreshMultiplayerScaling()
CompositeActorBehavior.as - GetMaxHp()




Line 169: Line 173:
|}
|}
'''Source''': AGameplayGameMode.as - RefreshMultiplayerScaling()
'''Source''': AGameplayGameMode.as - RefreshMultiplayerScaling()
=== NGP scaling stats ===
There's a 'hidden' scaling damage variable on enemies, adding 5% damage per NGP:
const float EnemyNGPBaseDmgMul = 0.05f;
'''Source''': Misc.as
== Curse ==
Sources of reduced curse gain are additive with each other. Players start at 0.60 curse gain. Reaching a threshold of -1 curse gain effectively reverses curse gain, causing you to lose it instead. This is doable by stacking Bishop's Blessed Bread (-0.1), Enduring Light (-0.25), Holy Water active (-1), Sacred Cross (-0.2 + -0.1 set bonus with Holy Water) for a total of -1.05. Other potential sources include Blessing of Light (-0.2) and Zeal enchants (-0.1).
'''''This needs testing confirmation'''''
'''Source''': PlayerRecord.as - float ScaleShadowCurse(float curses)
== Bosses ==
=== Shadow Face ===
Every 2 seconds, Shadow Face will check the number of active cultists and take damage based on their count. 7 active cultists will heal him for 1% of max hp.
{| class="wikitable"
|+ Damage
|-
! Cultists !! %hp dmg
|-
| 7 || -1%
|-
| 6 || 0.5%
|-
| 5 || 0.75%
|-
| 4 || 1%
|-
| 3 || 1.5%
|-
| 2 || 2%
|-
| 1 || 3%
|-
|0
|5%
|}
== Blacksmith Upgrade cost ==
Simplified:
Gold cost: minimum 100 or following formula: (item_level + (upgrade_level ^ 1.5 * 5) - (shop_level * 5)) * 25
Iron cost: minimum of 0 or following formula: upgrade_level - 1  + (item_level + 5 - (shop_level * 2)) / 10 / 2
m_cost = ShopCost(MaterialType::Gold, max(100, int(int(m_item.itemLevel) + pow(float(m_item.upgradeLevel), 1.5f) * 5 - shop.m_shopLevel * 5) * 25));
m_cost.AddCost(MaterialType::Iron, max(0, (int(m_item.upgradeLevel) - 1 + ((int(m_item.itemLevel) + 5 - shop.m_shopLevel * 2) / 10))) / 2);
'''Source''': EquipmentUpgradeShopContent.as - EquipmentUpgradeShopContentItem(EquipmentUpgradeShopContent@ shop, Equipment::Item@ item, uint index)
== Chapel Donations ==
Donation buff level: ((total_resources / divisor ) ^ 0.5) + 0.5
{| class="wikitable"
|+
!Resource
!Divisor
!Increase per level
|-
|Gold
|3000
|0.5% weapon damage
|-
|Wood
|10
|0.5% spell damage
|-
|Stone
|5
|((1 - 0.9975^level) * 100) % reduced damage taken
|-
|Iron
|2.5
|0.75% potion, regen and pickup health gain
|}
== Bannermen ==
{| class="wikitable"
|+
!Banner
!Effect
|-
|Bloodlust (red)
|50% speed (movement, attack, cast), 1.5 damage multiplier
|-
|Protection (gray)
|0.6 damage taken multiplier, 2.0 armour / resist multiplier
|-
|Healing (green)
|10% hp heal per second
|}
== Elixirs ==
Elixirs are found per character.
Each NG level increases your maximum elixirs found by 3 for each stat, for a total of 15.
You cannot find elixirs if your current amount found is equal or greater than your current NG's cap.
e.g. NG10 character has a cap of 30 in each stat, going down to NG5 won't allow you to find more than 15 elixirs for each stat.
Elixirs can have a greater value if the difference between your current amount gained and your cap at current NG is large enough.
{| class="wikitable"
|+
!Diff
!Amount gained
|-
|15+
|5
|-
|7+
|3
|-
|0+
|1
|}
{| class="wikitable"
|+Sources of Elixirs
!Source
!Chance
!Amount
|-
|Cursed cache
|50%
|1
|-
|Cursed chest
|60%
|1
|-
|Avatar
|100%
|3
|}

Latest revision as of 04:32, 3 March 2025

Sheepy's info compendium

EXP

Exp loss

If you're >10 levels below the area: xpMul=1.0+(lvlDiff+10)x0.15

Level Diff Exp Multi
-11 85%
-12 70%
-13 55%
-14 40%
-15 25%
-16 10%

If you're >5 levels above the area: xpMul=1.0+(5−lvlDiff)x0.15

Level Diff Exp Multi
+6 85%
+7 70%
+8 55%
+9 40%
+10 25%
+11 10%

Source: PlayerRecord.as - int GiveExperience(int amount, bool skipGainMod = false)

Architect Modifiers

Treasure Hunt

The treasury appears to have a 8% chance of spawning on each floor, with Treasure Hunt adding a separate 8% roll.

Without Treasure Hunt: ( 1 - ( 0.92 ^ 6 ) ) x 100 = 39.36% chance of seeing the treasury on a full run

With Treasure Hunt: ( 1 - ( 0.92 ^ 12 ) ) x 100 = 63.23% chance of seeing the treasury on a full run

Addendum: it is not guaranteed that the map generation succeeds in placing the treasury. More investigation required here.

Source: themes_dungeon.sval, themes_barracks.sval, themes_courts.sval - search for "treasury"

Righteous Flames

Applicable to Dungeon, Barracks and Courts. Appears to enable an extra Pyre prefab to the regular list of prefabs, unsure how much likelier this makes Pyres to appear. Needs investigation into level generation to understand the impact.

Weak Defenses

Reduces enemy density by 25%.

m_missionLevel.m_generator.m_enemyPlacer.m_densityMul *= 0.75f;


Source: MissionGameMode.as - void Start(uint8 peer, SValue@ save, StartMode sMode) override

Poor Training

50% chance to disable allowing Elite generation, for each enemy.

m_missionLevel.m_generator.m_enemyPlacer.m_allowElites = randf() < 0.5f;


Source: MissionGameMode.as - void Start(uint8 peer, SValue@ save, StartMode sMode) override

Scaling

Enemy HP

hp = ( base_hp + ng_level x 25 ) x ( 1 + mp_scaling x enemy_mp_scaling ) x ( 1 + enemy_ng_scaling x ng_level x 2.75 )

mp_scaling = (player_count - 1) x player_count ^ 0.35 + max(0, (player_count - 2) x 0.3f);

mp_scaling = 0 in solo

enemy_mp_scaling = 1

enemy_ng_scaling = 1 for everything except forest enemies at 0.5

The following table is for Avatar's 100k base hp

Solo
NGP HP
1 375,093.75
2 650,325.00
3 925,693.75
4 1,201,200.00
5 1,476,843.75
6 1,752,625.00
7 2,028,543.75
8 2,304,600.00
9 2,580,793.75
10 2,857,125.00

Source: CompositeActorBehavior.as - GetMaxHp() AGameplayGameMode.as - RefreshMultiplayerScaling()


Damage taken

An increased damage taken modifier is applied to all players, including from trap, scaling with number of players.

Code: g_mpPlrDmgTakenScale = clamp(pow(num, 0.2), 1.0f, 2.0f);

Simplified: player_count ^ 0.2 with a maximum of x2 at 32 players.

Players Damage taken
1 1
2 1.148
3 1.245
4 1.310
5 1.379
6 1.430
7 1.475
... ...
32 2

Source: AGameplayGameMode.as - RefreshMultiplayerScaling()

NGP scaling stats

There's a 'hidden' scaling damage variable on enemies, adding 5% damage per NGP: const float EnemyNGPBaseDmgMul = 0.05f;

Source: Misc.as


Curse

Sources of reduced curse gain are additive with each other. Players start at 0.60 curse gain. Reaching a threshold of -1 curse gain effectively reverses curse gain, causing you to lose it instead. This is doable by stacking Bishop's Blessed Bread (-0.1), Enduring Light (-0.25), Holy Water active (-1), Sacred Cross (-0.2 + -0.1 set bonus with Holy Water) for a total of -1.05. Other potential sources include Blessing of Light (-0.2) and Zeal enchants (-0.1).

This needs testing confirmation

Source: PlayerRecord.as - float ScaleShadowCurse(float curses)

Bosses

Shadow Face

Every 2 seconds, Shadow Face will check the number of active cultists and take damage based on their count. 7 active cultists will heal him for 1% of max hp.

Damage
Cultists %hp dmg
7 -1%
6 0.5%
5 0.75%
4 1%
3 1.5%
2 2%
1 3%
0 5%

Blacksmith Upgrade cost

Simplified:

Gold cost: minimum 100 or following formula: (item_level + (upgrade_level ^ 1.5 * 5) - (shop_level * 5)) * 25

Iron cost: minimum of 0 or following formula: upgrade_level - 1 + (item_level + 5 - (shop_level * 2)) / 10 / 2


m_cost = ShopCost(MaterialType::Gold, max(100, int(int(m_item.itemLevel) + pow(float(m_item.upgradeLevel), 1.5f) * 5 - shop.m_shopLevel * 5) * 25));

m_cost.AddCost(MaterialType::Iron, max(0, (int(m_item.upgradeLevel) - 1 + ((int(m_item.itemLevel) + 5 - shop.m_shopLevel * 2) / 10))) / 2);


Source: EquipmentUpgradeShopContent.as - EquipmentUpgradeShopContentItem(EquipmentUpgradeShopContent@ shop, Equipment::Item@ item, uint index)

Chapel Donations

Donation buff level: ((total_resources / divisor ) ^ 0.5) + 0.5

Resource Divisor Increase per level
Gold 3000 0.5% weapon damage
Wood 10 0.5% spell damage
Stone 5 ((1 - 0.9975^level) * 100) % reduced damage taken
Iron 2.5 0.75% potion, regen and pickup health gain

Bannermen

Banner Effect
Bloodlust (red) 50% speed (movement, attack, cast), 1.5 damage multiplier
Protection (gray) 0.6 damage taken multiplier, 2.0 armour / resist multiplier
Healing (green) 10% hp heal per second

Elixirs

Elixirs are found per character.

Each NG level increases your maximum elixirs found by 3 for each stat, for a total of 15.

You cannot find elixirs if your current amount found is equal or greater than your current NG's cap.

e.g. NG10 character has a cap of 30 in each stat, going down to NG5 won't allow you to find more than 15 elixirs for each stat.


Elixirs can have a greater value if the difference between your current amount gained and your cap at current NG is large enough.

Diff Amount gained
15+ 5
7+ 3
0+ 1
Sources of Elixirs
Source Chance Amount
Cursed cache 50% 1
Cursed chest 60% 1
Avatar 100% 3