Difficulty scaling: Difference between revisions

Marked this version for translation
No edit summary
(Marked this version for translation)
Line 5: Line 5:
'''Difficulty scaling''' is a mechanic in ''Breath of the Wild'' that results in enemies and weapons being progressively replaced by more powerful variants during a playthrough.
'''Difficulty scaling''' is a mechanic in ''Breath of the Wild'' that results in enemies and weapons being progressively replaced by more powerful variants during a playthrough.


<!--T:2-->
== Points == <!--T:2-->
== Points ==


<!--T:68-->
The scaling system is based on a point system. Killing enemies is the ''only way'' to receive points.
The scaling system is based on a point system. Killing enemies is the ''only way'' to receive points.


Line 28: Line 28:
The subsystem provides two functions ([[Difficulty scaling#Ecosystem::LevelSensor::scaleWeapon|<code>scaleWeapon</code>]] and [[Difficulty scaling#Ecosystem::LevelSensor::scaleActor|<code>scaleActor</code>]]) that may be called when a weapon or enemy actor is created.
The subsystem provides two functions ([[Difficulty scaling#Ecosystem::LevelSensor::scaleWeapon|<code>scaleWeapon</code>]] and [[Difficulty scaling#Ecosystem::LevelSensor::scaleActor|<code>scaleActor</code>]]) that may be called when a weapon or enemy actor is created.


<!--T:7-->
== Scaling inhibitors == <!--T:7-->  
== Scaling inhibitors ==


<!--T:69-->
Both scaling functions will immediately return without doing anything if:
Both scaling functions will immediately return without doing anything if:
* [[WorldMgr]]::sInstance-&#x3E;stageType == 1 (Open World [[stage]])
* [[WorldMgr]]::sInstance-&#x3E;stageType == 1 (Open World [[stage]])
Line 37: Line 37:
Scaling will also be skipped if the current [[map area]] is 28. This corresponds to &#x22;HateruSea&#x22;, which is the Eventide Island area.
Scaling will also be skipped if the current [[map area]] is 28. This corresponds to &#x22;HateruSea&#x22;, which is the Eventide Island area.


<!--T:8-->
== Weapons == <!--T:8-->
== Weapons ==
'scaleWeapon' is called (i.e. weapons may be scaled) for a weapon if:
'scaleWeapon' is called (i.e. weapons may be scaled) for a weapon if:
* '''For standalone weapons''': The actor property 'LevelSensorMode' is higher than 1 '''and''' it wasn't already picked up.
* '''For standalone weapons''': The actor property 'LevelSensorMode' is higher than 1 '''and''' it wasn't already picked up.
Line 45: Line 44:
* '''For other enemy drops''': The flag <code>{MapName}_WeaponDrop_{ID}</code> is false, '''and''' [the actor property 'LevelSensorMode' is higher than 1 ''or'' the enemy is a Guardian Scout ('Enemy_Guardian_Mini')].
* '''For other enemy drops''': The flag <code>{MapName}_WeaponDrop_{ID}</code> is false, '''and''' [the actor property 'LevelSensorMode' is higher than 1 ''or'' the enemy is a Guardian Scout ('Enemy_Guardian_Mini')].


<!--T:70-->
Note: Weapons that are bought from a shop cannot receive modifiers because they do not fit into any of the above cases.
Note: Weapons that are bought from a shop cannot receive modifiers because they do not fit into any of the above cases.


<!--T:9-->
== Weapon bonuses == <!--T:9-->
== Weapon bonuses ==


<!--T:71-->
Scaling of weapons are divided into three steps: Does the weapon get replaced by a different (better weapon)?
Scaling of weapons are divided into three steps: Does the weapon get replaced by a different (better weapon)?
Which of the stats (among attack, guard, durability etc) is increased?
Which of the stats (among attack, guard, durability etc) is increased?
And how much is it increased.
And how much is it increased.


<!--T:61-->
=== Bonus values === <!--T:61-->
=== Bonus values ===


<!--T:72-->
Bonus values (e.g. the durability or attack power increase) are determined from [[ActorParam/GeneralParamList]] (with a copy of the information in [[ActorInfoData]]). Valid ranges and bonuses for each weapon are configured in the WeaponCommon section.
Bonus values (e.g. the durability or attack power increase) are determined from [[ActorParam/GeneralParamList]] (with a copy of the information in [[ActorInfoData]]). Valid ranges and bonuses for each weapon are configured in the WeaponCommon section.


<!--T:10-->
==== amiibo ==== <!--T:10-->
==== amiibo ====
</translate>
</translate>
{|class="wikitable"
{|class="wikitable"
! <translate>Bonus</translate> !! <translate>Value that is used for the bonus effect</translate>
! <translate><!--T:73--> Bonus</translate> !! <translate><!--T:74--> Value that is used for the bonus effect</translate>
|-
|-
| <translate>None</translate> || -
| <translate><!--T:75--> None</translate> || -
|-
|-
| <translate>Attack up</translate> || <translate>addAtkMax</translate>
| <translate><!--T:76--> Attack up</translate> || <translate><!--T:77--> addAtkMax</translate>
|-
|-
| <translate>Durability up</translate> || <translate>addLifeMax</translate>
| <translate><!--T:78--> Durability up</translate> || <translate><!--T:79--> addLifeMax</translate>
|-
|-
| <translate>Long throw</translate> || <translate>addThrowMax</translate>
| <translate><!--T:80--> Long throw</translate> || <translate><!--T:81--> addThrowMax</translate>
|-
|-
| <translate>Multi-shot burst (bows)</translate> || <translate>5-shot burst</translate>
| <translate><!--T:82--> Multi-shot burst (bows)</translate> || <translate><!--T:83--> 5-shot burst</translate>
|-
|-
| <translate>Quick shot (bows)</translate> || <translate>addRapidFireMin</translate>
| <translate><!--T:84--> Quick shot (bows)</translate> || <translate><!--T:85--> addRapidFireMin</translate>
|-
|-
| <translate>AddSurfMaster</translate> || [[bgparamlist#Global|GlobalParameter]]::shieldSurfMasterFrictionRatio
| <translate><!--T:86--> AddSurfMaster</translate> || [[bgparamlist#Global|GlobalParameter]]::shieldSurfMasterFrictionRatio
|-
|-
| <translate>Shield guard up</translate> || <translate>addGuardMax</translate>
| <translate><!--T:87--> Shield guard up</translate> || <translate><!--T:88--> addGuardMax</translate>
|}
|}


Line 87: Line 86:
No randomness is involved.
No randomness is involved.


<!--T:11-->
==== Non-amiibo ==== <!--T:11-->
==== Non-amiibo ====
</translate>
</translate>


{|class="wikitable"
{|class="wikitable"
! <translate>Bonus</translate> !! <translate>Value that is used for the bonus effect</translate>
! <translate><!--T:89--> Bonus</translate> !! <translate><!--T:90--> Value that is used for the bonus effect</translate>
|-
|-
| <translate>None</translate> || -
| <translate><!--T:91--> None</translate> || -
|-
|-
| <translate>Attack up</translate> || <translate>Random integer between addAtkMin and addAtkMax</translate>
| <translate><!--T:92--> Attack up</translate> || <translate><!--T:93--> Random integer between addAtkMin and addAtkMax</translate>
|-
|-
| <translate>Durability up</translate> || <translate>Random integer between addLifeMin and addLifeMax</translate>
| <translate><!--T:94--> Durability up</translate> || <translate><!--T:95--> Random integer between addLifeMin and addLifeMax</translate>
|-
|-
| <translate>Long throw</translate> || <translate>Random float between addThrowMin and addThrowMax</translate>
| <translate><!--T:96--> Long throw</translate> || <translate><!--T:97--> Random float between addThrowMin and addThrowMax</translate>
|-
|-
| <translate>Multi-shot burst (bows)</translate> || <translate>5-shot burst</translate>
| <translate><!--T:98--> Multi-shot burst (bows)</translate> || <translate><!--T:99--> 5-shot burst</translate>
|-
|-
| <translate>Quick shot (bows)</translate> || <translate>Random float between addRapidFireMin and addRapidFireMax</translate>
| <translate><!--T:100--> Quick shot (bows)</translate> || <translate><!--T:101--> Random float between addRapidFireMin and addRapidFireMax</translate>
|-
|-
| <translate>AddSurfMaster</translate> || <translate>[[bgparamlist#Global|GlobalParameter]]::shieldSurfMasterFrictionRatio</translate>
| <translate><!--T:102--> AddSurfMaster</translate> || <translate><!--T:103--> [[bgparamlist#Global|GlobalParameter]]::shieldSurfMasterFrictionRatio</translate>
|-
|-
| <translate>Shield guard up</translate> || <translate>Random integer between addGuardMin and addGuardMax</translate>
| <translate><!--T:104--> Shield guard up</translate> || <translate><!--T:105--> Random integer between addGuardMin and addGuardMax</translate>
|}
|}


Line 115: Line 113:
In summary, for non-amiibo weapons, an attack up results in a randomized attack.
In summary, for non-amiibo weapons, an attack up results in a randomized attack.


<!--T:12-->
=== Bonus types === <!--T:12-->
=== Bonus types ===


<!--T:106-->
Weapon bonuses (e.g. Durability Up, Attack Up) are entirely random. Each bonus has equal probability.
Weapon bonuses (e.g. Durability Up, Attack Up) are entirely random. Each bonus has equal probability.
</translate>
</translate>
Line 123: Line 121:
<!--T:13-->
<!--T:13-->
{|class="wikitable"
{|class="wikitable"
! <translate>Bonus</translate> !! <translate>Available in modifier tiers</translate>
! <translate><!--T:107--> Bonus</translate> !! <translate><!--T:108--> Available in modifier tiers</translate>
|-
|-
|-
|-
| <translate>Attack up</translate> || <translate>Blue/White and Yellow</translate>
| <translate><!--T:109--> Attack up</translate> || <translate><!--T:110--> Blue/White and Yellow</translate>
|-
|-
| <translate>Durability up</translate> || <translate>Blue/White and Yellow</translate>
| <translate><!--T:111--> Durability up</translate> || <translate><!--T:112--> Blue/White and Yellow</translate>
|-
|-
| <translate>Long throw</translate> || <translate>Yellow</translate>
| <translate><!--T:113--> Long throw</translate> || <translate><!--T:114--> Yellow</translate>
|-
|-
| <translate>Multi-shot burst (bows)</translate> || <translate>Yellow</translate>
| <translate><!--T:115--> Multi-shot burst (bows)</translate> || <translate><!--T:116--> Yellow</translate>
|-
|-
| <translate>Quick shot (bows)</translate> || <translate>Yellow</translate>
| <translate><!--T:117--> Quick shot (bows)</translate> || <translate><!--T:118--> Yellow</translate>
|-
|-
| <translate>AddSurfMaster</translate> || <translate>Yellow</translate>
| <translate><!--T:119--> AddSurfMaster</translate> || <translate><!--T:120--> Yellow</translate>
|-
|-
| <translate>Shield guard up</translate> || <translate>Blue/White and Yellow</translate>
| <translate><!--T:121--> Shield guard up</translate> || <translate><!--T:122--> Blue/White and Yellow</translate>
|-
|-
| <translate>Critical Hit</translate> || <translate>Blue/White</translate>
| <translate><!--T:123--> Critical Hit</translate> || <translate><!--T:124--> Blue/White</translate>
|-
|-
| <translate>ZoomRapid</translate> || <translate>Yellow</translate>
| <translate><!--T:125--> ZoomRapid</translate> || <translate><!--T:126--> Yellow</translate>
|}
|}


Line 149: Line 147:
Note that "Critical Hit" can only be selected if weaponCommonSharpWeaponAddCrit is true ''and'' if the weapon modifier tier is Blue/White. This means that it becomes impossible to get a weapon with a Critical Hit bonus after enough enemies have been killed.
Note that "Critical Hit" can only be selected if weaponCommonSharpWeaponAddCrit is true ''and'' if the weapon modifier tier is Blue/White. This means that it becomes impossible to get a weapon with a Critical Hit bonus after enough enemies have been killed.


<!--T:15-->
== Enemies == <!--T:15-->
== Enemies ==


<!--T:127-->
When loading enemies, the game will always try to scale enemies.
When loading enemies, the game will always try to scale enemies.


Line 165: Line 163:
</translate>
</translate>
{| class="wikitable"
{| class="wikitable"
! <translate>Parameter</translate>
! <translate><!--T:128--> Parameter</translate>
! <translate>Default</translate>
! <translate><!--T:129--> Default</translate>
! <translate>Description</translate>
! <translate><!--T:130--> Description</translate>
|-
|-
| IsHardModeActor
| IsHardModeActor
| false
| false
| <translate>Controls whether an enemy only shows up in Master Mode.</translate>
| <translate><!--T:131--> Controls whether an enemy only shows up in Master Mode.</translate>
|-
|-
| DisableRankUpForHardMode
| DisableRankUpForHardMode
| false
| false
| <translate>Controls whether the automatic rankup applies to an enemy.</translate>
| <translate><!--T:132--> Controls whether the automatic rankup applies to an enemy.</translate>
|}
|}
<translate>
<translate>
<!--T:133-->
In Master Mode, IsHardModeActor, DisableRankUpForHardMode and LevelSensorMode are combined on some actors to keep low-level enemies in the overworld (e.g. Red Bokoblin south of the Great Plateau).
In Master Mode, IsHardModeActor, DisableRankUpForHardMode and LevelSensorMode are combined on some actors to keep low-level enemies in the overworld (e.g. Red Bokoblin south of the Great Plateau).


<!--T:18-->
== Properties == <!--T:18-->
== Properties ==


<!--T:19-->
=== <code>LevelSensorMode</code> === <!--T:19-->
=== <code>LevelSensorMode</code> ===
This actor property controls whether scaling is enabled for an enemy or weapon. Also applies to any weapons held by an enemy since 'scaleWeapon' is called when an enemy drops their weapon.
This actor property controls whether scaling is enabled for an enemy or weapon. Also applies to any weapons held by an enemy since 'scaleWeapon' is called when an enemy drops their weapon.


Line 190: Line 187:
Note that this doesn't apply to weapons that are attached to a Hinox's necklace, because Hinoxes use a different underlying enemy actor which overrides the 'on weapon dropped' function and ignores 'LevelSensorMode'.
Note that this doesn't apply to weapons that are attached to a Hinox's necklace, because Hinoxes use a different underlying enemy actor which overrides the 'on weapon dropped' function and ignores 'LevelSensorMode'.


<!--T:21-->
=== <code>SharpWeaponJudgeType</code> === <!--T:21-->
=== <code>SharpWeaponJudgeType</code> ===
This actor property controls the ''minimum'' modifier tier that a weapon can receive.
This actor property controls the ''minimum'' modifier tier that a weapon can receive.


Line 198: Line 194:
</translate>
</translate>
{| class="wikitable"
{| class="wikitable"
! <translate>Value</translate>
! <translate><!--T:134--> Value</translate>
! <translate>Description</translate>
! <translate><!--T:135--> Description</translate>
|-
|-
| 0
| 0
| <translate>'''None''': No modifiers.</translate>
| <translate><!--T:136--> '''None''': No modifiers.</translate>
|-
|-
| 1
| 1
| <translate>'''RandomBlue''': Weapon will randomly get at least a blue modifier (with <code>weaponCommonSharpWeaponPer</code> being the probability).</translate>
| <translate><!--T:137--> '''RandomBlue''': Weapon will randomly get at least a blue modifier (with <code>weaponCommonSharpWeaponPer</code> being the probability).</translate>
|-
|-
| 2
| 2
| <translate>'''Blue''': Weapon will get at least a blue modifier.</translate>
| <translate><!--T:138--> '''Blue''': Weapon will get at least a blue modifier.</translate>
|-
|-
| 3
| 3
| <translate>'''Yellow''': Weapon will get at least a yellow modifier.</translate>
| <translate><!--T:139--> '''Yellow''': Weapon will get at least a yellow modifier.</translate>
|-
|-
| 4
| 4
| <translate>'''NoneForced''' (chests only): Weapon will ''never'' spawn with any modifiers. ''This overrides regular scaling.''</translate>
| <translate><!--T:140--> '''NoneForced''' (chests only): Weapon will ''never'' spawn with any modifiers. ''This overrides regular scaling.''</translate>
|}
|}


Line 227: Line 223:
For example, 0 ('None') doesn't mean a weapon will never receive a modifier. It just means that the developers haven't forced the weapon to spawn with a blue/yellow modifier. If scaling requirements are satisfied, the weapon will receive blue or yellow modifiers.
For example, 0 ('None') doesn't mean a weapon will never receive a modifier. It just means that the developers haven't forced the weapon to spawn with a blue/yellow modifier. If scaling requirements are satisfied, the weapon will receive blue or yellow modifiers.


<!--T:26-->
== Scaling algorithm == <!--T:26-->
== Scaling algorithm ==


<!--T:27-->
=== <code>Ecosystem::LevelSensor::loadByml</code> === <!--T:27-->
=== <code>Ecosystem::LevelSensor::loadByml</code> ===


<!--T:141-->
This function is called by <code>Ecosystem::init</code> from <code>ksys::InitializeApp</code>
This function is called by <code>Ecosystem::init</code> from <code>ksys::InitializeApp</code>


Line 238: Line 233:
Sets up byml structures for reading Ecosystem/[[LevelSensor.byml]].
Sets up byml structures for reading Ecosystem/[[LevelSensor.byml]].


<!--T:29-->
=== <code>Ecosystem::LevelSensor::calculatePoints</code> === <!--T:29-->
=== <code>Ecosystem::LevelSensor::calculatePoints</code> ===


<!--T:142-->
Called by [[PlacementMgr]] when spawning actors.
Called by [[PlacementMgr]] when spawning actors.


Line 259: Line 254:
     points += kill_count * kill_flag["point"];
     points += kill_count * kill_flag["point"];


<!--T:143-->
this->points = points;
this->points = points;
this->weapon_points = points * this->byml["setting"].Level2WeaponPower;
this->weapon_points = points * this->byml["setting"].Level2WeaponPower;
Line 267: Line 263:
In practice, settings have never been modified. 1.5.0 (which will likely be the last game update) still has the same Level2WeaponPower and Level2EnemyPower.
In practice, settings have never been modified. 1.5.0 (which will likely be the last game update) still has the same Level2WeaponPower and Level2EnemyPower.


<!--T:34-->
=== <code>Ecosystem::LevelSensor::scaleWeapon</code> === <!--T:34-->
=== <code>Ecosystem::LevelSensor::scaleWeapon</code> ===


<!--T:144-->
Called from treasure chest code, enemy actors{{Check}}, <code>Ecosystem::LevelSensor::scaleActor</code>
Called from treasure chest code, enemy actors{{Check}}, <code>Ecosystem::LevelSensor::scaleActor</code>


Line 336: Line 332:
</source>
</source>


<!--T:46-->
=== <code>Ecosystem::LevelSensor::scaleActor</code> === <!--T:46-->
=== <code>Ecosystem::LevelSensor::scaleActor</code> ===


<!--T:145-->
Analogous to <code>LevelSensor::scaleWeapon</code>.
Analogous to <code>LevelSensor::scaleWeapon</code>.


Line 391: Line 387:
</source>
</source>


<!--T:54-->
== The Data == <!--T:54-->
== The Data ==


<!--T:146-->
To make things easier to understand, here are links to:
To make things easier to understand, here are links to:
* [https://docs.google.com/spreadsheets/d/e/2PACX-1vRSlyOD7FLAn1TUBn64Pu8Pld-WOfgcVByuywHMWvBTEV0j8potD1wkBs-MJJXf-gvEkpfItUCMqMk6/pubhtml kill point, enemy scaling and weapon scaling tables]
* [https://docs.google.com/spreadsheets/d/e/2PACX-1vRSlyOD7FLAn1TUBn64Pu8Pld-WOfgcVByuywHMWvBTEV0j8potD1wkBs-MJJXf-gvEkpfItUCMqMk6/pubhtml kill point, enemy scaling and weapon scaling tables]
Line 399: Line 395:
This makes it possible to see both the required points for enemy/weapon upgrades, as well as all of the special cases extremely easily.
This makes it possible to see both the required points for enemy/weapon upgrades, as well as all of the special cases extremely easily.


<!--T:55-->
== Ganon Blights == <!--T:55-->
== Ganon Blights ==


<!--T:147-->
Ganon blights also have varying difficulty but follow a different system. Their health is determined by the base HP (set in [[ActorParam/GeneralParamList|GeneralParamList]]) and blight defeat flags.
Ganon blights also have varying difficulty but follow a different system. Their health is determined by the base HP (set in [[ActorParam/GeneralParamList|GeneralParamList]]) and blight defeat flags.


<!--T:148-->
<source lang="c++">__int64 SiteBoss::getInitialHP(SiteBoss *this) // 0x71002D01F4
<source lang="c++">__int64 SiteBoss::getInitialHP(SiteBoss *this) // 0x71002D01F4
{
{
Line 423: Line 420:
}</source>
}</source>


<!--T:149-->
Effectively, this means that the first blight Link fights will have 800+0×400 = 800 HP, the second will have 800+1×400 = 1200 HP, the third 800+2×400 = 1600 HP and the last one 800+3×400 = 2000 HP.
Effectively, this means that the first blight Link fights will have 800+0×400 = 800 HP, the second will have 800+1×400 = 1200 HP, the third 800+2×400 = 1600 HP and the last one 800+3×400 = 2000 HP.


<!--T:56-->
=== Special case 1: Castle Blights === <!--T:56-->
=== Special case 1: Castle Blights ===


<!--T:150-->
Castle blights have <code>IsRemainBoss</code> set to false in their root AI parameters (see [[AIDef:AI/SiteBossSpearRoot]] for example), which sets flag 4.
Castle blights have <code>IsRemainBoss</code> set to false in their root AI parameters (see [[AIDef:AI/SiteBossSpearRoot]] for example), which sets flag 4.


Line 436: Line 434:
If flag 4 is set, the [[AIDef:Action/SiteBossDie]] code will NOT increment the &#x22;defeated&#x22; counter. This means castle blights do not give any scaling points.
If flag 4 is set, the [[AIDef:Action/SiteBossDie]] code will NOT increment the &#x22;defeated&#x22; counter. This means castle blights do not give any scaling points.


<!--T:59-->
=== Special case 2: DLC2 Blights === <!--T:59-->
=== Special case 2: DLC2 Blights ===


<!--T:151-->
Illusory Realm blights possess the <code>EnemySiteBoss_R</code> actor tag. This causes flag 8 to be set. So they will always have 500+4×250 = 1500 HP.
Illusory Realm blights possess the <code>EnemySiteBoss_R</code> actor tag. This causes flag 8 to be set. So they will always have 500+4×250 = 1500 HP.


Line 444: Line 442:
Interestingly, the Windblight AI function relies doesn't check the actor tag but the actor name instead. For flag 8 to be set, the actor name must be <code>Enemy_SiteBoss_Bow_R</code>.
Interestingly, the Windblight AI function relies doesn't check the actor tag but the actor name instead. For flag 8 to be set, the actor name must be <code>Enemy_SiteBoss_Bow_R</code>.


<!--T:152-->
<references />
<references />
[[Category:Internals]]
[[Category:Internals]]