Fire Emblem Heroes Wiki
Advertisement

Resonant Battles growth settings[ | ]

The internal level of all thieves and guardians is the highest level of the player's units in the team, plus a value (lv_offset*) that depends on the player's Interval and chosen battle difficulty:

Interval 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
Beginner -8 -8 -7 -7 -6 -6 -5 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8
Intermediate -4 -4 -3 -3 -2 -2 -1 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
Advanced 0 0 1 1 2 2 3 3 4 5 6 7 8 9 10 11 12 13 14 15 16

For example, entering a Resonant Battle at Advanced difficulty with a Lv. 40 team on Interval 21 results in an internal level of 56. Enemy stats are then calculated from their base stat values and growth rates. After that, thief stats are corrected as follows:

  • The HP stat is multiplied by 150%. (multiplier)
  • The Def/Res stats are raised to 50% of the unit's internal level if they are lower than that. (min_final_growth)
  • A random bonus between 0 and 3 (inclusive) is added to every stat. (random_add)

Guardian stats are corrected as follows:

  • The HP and Atk stats are multiplied by 150%.
  • The Def/Res stats are raised to 75% of the unit's internal level if they are lower than that.
  • A random bonus between 0 and 3 (inclusive) is added to every stat.

Random skills[ | ]

Training Tower, Tempest Trials, and Allegiance Battles may equip random skills on units.

Game mode Heroes Enemy units
When random skills may be filled Random skill pool When random skills may be filled Random skill pool
Training Tower Never ~ always (2nd Stratum and below never equip non-weapon skills, 10th Stratum always equip all skills) Skills owned by the Hero in that category, plus skill on the corresponding unit from the base map (at Normal difficulty), if its tt_inherit_base is true (10th Stratum only), promoted according to derived map rules; all skills with random_mode == 1 if this pool has no legal skills Never ~ often (2nd Stratum and below never equip non-weapon skills) All skills with random_mode == 1
Tempest Trials When the Hero owns any skill from that category (it seems empty slots are also filled at above LV.40) Skills owned by the Hero in that category; all skills with random_mode == 1 if this pool has no legal skills N/A N/A
Allegiance Battles When the Hero does not own a skill at their rarity, otherwise the Hero equips that skill; Assists are never filled All skills with random_mode == 1 All non-Assist skills may be filled All skills with random_mode == 1

Only legal skills from the random pool may be equipped. This means:

  • The unit must be able to inherit the skill normally;
  • The unit's level is between skill_definition::min_lv and max_lv;
  • random_allowed is non-zero;
  • random_mode is 1 or 2.

Heroes do not own evolved and refined weapons; additionally, random Heroes cannot equip any weapons they do not already own (note that weapon skills never have tt_inherit_base set).

Growth percentages[ | ]

The game internally stores growth rates of all Heroes and generic units as percentages. Only multiples of 5% are ever used; however, growth rates are defined for growth percentages that are not multiples of 5 (this has been verified by a debugger). The growth percentage is multiplied by an additional rarity factor:

★ ★ ★ ★ ★
0.86 0.93 1.00 1.07 1.14

The truncated result produces the following master growth table:

GP ★ ★ ★ ★ ★
-4 0 0 0 0 0
-3 4 4 5 5 5
-2 8 9 10 10 11
-1 12 13 15 16 17
0 17 18 20 21 22
1 21 23 25 26 28
2 25 27 30 32 34
3 30 32 35 37 39
4 34 37 40 42 45
5 38 41 45 48 51
6 43 46 50 53 57
7 47 51 55 58 62
8 51 55 60 64 68
9 55 60 65 69 74
10 60 65 70 74 79
11 64 69 75 80 85
12 68 74 80 85 91
13 73 79 85 90 96

This table is used directly for the randomization of stat growth tables (see below). Stat growth values can be derived from this table by GrowthValue = trunc(0.39 × GrowthPercent), or directly calculated by GrowthValue = trunc(0.39 × trunc((GrowthPoint × 5 + 20) × (0.79 + 0.07 × Rarity))).

Enemy stats for derived maps[ | ]

Certain game modes (Chain Challenge, Squad Assault, Blessed Gardens) derive their maps from existing story / paralogue maps. Chain Challenge scenarios use base maps at their respective difficulties, whereas the other two game modes always use base maps at Lunatic. Their stats are determined as follows:

  • First, if the unit's rarity is increased, then the usual base stat changes for playable Heroes apply, using the base stats defined in either hero_definition or enemy_definition.
  • Each stat is increased by trunc((newGP × (newLv - 1) - oldGP × (origLv - 1)) ÷ 100), where origLv is the unit's original level, newLvorigLv is the new level, oldGP is the growth percentage at the unit's old rarity, and newGPoldGP is the growth percentage at the new rarity. Levels above 40 are defined as follows:
Game mode Difficulty Levels
Chain Challenge Lunatic, single-chapter Story 40/41/42/43/45
Hard, double-chapter Story 40/40/41/41/43/42/42/43/43/45
Lunatic, double-chapter Story 45/45/46/46/48/47/47/48/48/50
Lunatic, single-chapter Paralogue 40/42/45
Hard, double-chapter Paralogue 40/41/43/42/43/45
Lunatic, double-chapter Paralogue 45/46/48/47/48/50
Squad Assault Lunatic 50/50/50/50/50
Blessed Gardens Lunatic 45
Infernal 50
Blessed Grounds Odd-numbered Grounds 45
Even-numbered Grounds 50
Tempest Trials Lunatic, Lv. 40 40/41/42/43/44/45/45
A few special cases:
  • If only the level is changed, the formula reduces to trunc(GP × (newLv - origLv) ÷ 100).
  • If only the rarity is changed, the formula reduces to trunc((newGP - oldGP) × (Lv - 1) ÷ 100).
  • If both rarity and level are unchanged, no stat boosts occur at this stage.
  • The HP of all enemies is further calculated as trunc(HP × HPFactor), where HPFactor is a global multiplier that depends only on the game mode:
Game mode Difficulty HP factor
Chain Challenge Normal, single-chapter 1.1
Hard, single-chapter 1.2
Lunatic, single-chapter 1.3
Normal, double-chapter Story 1.1 for first half, 1.2 for second half
Hard, double-chapter Story 1.2 for first half, 1.3 for second half
Lunatic, double-chapter Story 1.3 for first half, 1.4 for second half
Normal, double-chapter Paralogue 1.1
Hard, double-chapter Paralogue 1.2
Lunatic, double-chapter Paralogue 1.3
Squad Assault Lunatic 1.3
Blessed Gardens Normal 0.8
Hard 0.8
Lunatic 1.1
Infernal 1.5
Blessed Grounds Odd-numbered Grounds 1.1
Even-numbered Grounds 1.5
Tempest Trials Normal, Lv. 8 0.90/0.90/0.90
Normal, Lv. 14 0.90/0.90/0.95
Normal, Lv. 20 0.95/0.95/1.00
Hard, Lv. 25 1.00/1.00/1.00/1.05
Hard, Lv. 30 1.00/1.00/1.05/1.05/1.10
Lunatic, Lv. 35 1.00/1.05/1.10/1.15/1.20
Lunatic, Lv. 40 1.00/1.05/1.10/1.15/1.20/1.25/1.30
  • Skills are promoted as follows:
    • While skill_definition::next_skill points to a valid skill name, and the unit's rarity is higher than or equal to skill_definition::promotion_rarity, the current skill is replaced by skill_definition::next_skill; this continues until no more promotions can be made. Skills are never demoted, and promotion takes place even if the unit's rarity does not change between the base map and the derived map. Empty skill slots in the base map are never occupied in derived maps.
    • Additionally, only skills with skill_definition::promotion_tier nonzero and also less than or equal to a per-map tier are allowed to promote. Currently this tier number is always 1 on scenarios for derived maps, so Staff weapons, Assists, and Specials are never promoted (see table below).
    • Slight deviations occur for weapon promotion depending on whether the unit is a Hero or an enemy:
      • If a Hero owns the original weapon skill, and the promotion_tier check passes, their default weapon at the new rarity is chosen.
      • If an enemy unit is at 5 ★ and its enemy_definition::top_weapon refers to a valid weapon skill, that skill is chosen, regardless of its promotion_tier value, and regardless of which original weapon skill the unit has (unless it didn't have a weapon).

(Random enemy stats, like those in Tempest Trials and Training Tower, have not been determined. HP factors for Tempest Trials are shown for convenience.)

next_skill exists if and only if the skill is inheritable, not a Sacred Seal, and both promotion_rarity and promotion_tier are nonzero. The table below lists the skill types that have canonical upgrades:

Skills promotion_rarity promotion_tier next_skill
Rank 1 non-staff weapons 3 1 Corresponding rank 2 weapon
Rank 2 non-staff weapons 4 1 Rank 3 weapon with same effect and higher Might
Rank 3 non-staff weapons (excluding generic beast weapons e.g. Skilliconweapon Adult (Flier)) 5 1 Corresponding rank 4 weapon
Rank 1 staff weapons (Icon Class Colorless Staff Assault) 3 2 Icon Class Colorless Staff Fear
Rank 2 staff weapons 5 2 Corresponding rank 3 weapon
Rank 1 staff Assists (Skilliconassist Heal) 3 2 Skilliconassist Mend
Rank 2 staff Assists (Skilliconassist Mend, Skilliconassist Reconcile) 4 2 Skilliconassist Recover and Skilliconassist Martyr respectively
Rank 3 staff Assists 5 2 Corresponding rank 4 Assist
Rank 1 offensive / defensive Specials 4 2 Rank 2 Special with stronger effect but same cooldown count (e.g. Skilliconspecial New MoonSkilliconspecial Luna Skilliconspecial Moonbow)
Rank 1 Passives (excluding single-rank skills e.g. Lunge Lunge) 4 1 Corresponding rank 2 Passive
Rank 2 Passives 5 1 Corresponding rank 3 Passive

Growth vectors[ | ]

The file Common/SRPG/Grow.bin.lz contains the seemingly random growth vectors used in the game. The decompressed file contains 2496 XOR-encrypted 64-bit little-endian bit vectors starting from address 0x30, where the n-th bit indicates whether a given stat should increase when the hero reaches level n. An example of reading the vectors directly from the binary file:

#!/usr/bin/env ruby

# this cipher is hardcoded inside libcocos2dcpp.so and appears exactly once
CIPHER = [0x0C, 0xE6, 0xBB, 0x0C, 0x1D, 0x0F, 0x1E, 0xA8]

File.open(File.join('Common', 'SRPG', 'Grow.bin'), 'rb') do |f|
  f.seek 0x30
  (39 * 64).times do |vec_id|
    bytes = f.read(8).bytes
    bytes_xor = bytes.zip(CIPHER).map {|x, y| x ^ y}
    bits = Array.new(64) {|i| bytes_xor[i / 8][i % 8]}
    puts vec_id.to_s + ': ' + bits.join
  end
end

For example, Brave Lyn's neutral growth vectors are: (the used portions are shown in boldface)

Stat Vector ID
HP 00100011 01100010 10110110 11100100 01001100 10000000 00000000 00000000 29
Atk 00011111 11001111 01110110 10101101 10101110 00000000 00000000 00000000 26
Spd 00001111 00110111 01011101 11111110 11010100 10000000 00000000 00000000 39
Def 00001010 00000000 01110010 00111111 00010000 00000000 00000000 00000000 00
Res 00011111 00001110 01110010 10011101 01110100 10000000 00000000 00000000 33

Here ID is the lowest 6 bits of the vec_id field, as there are 64 possible variations for each stat growth amount between 1 and 39. This growth vector ID, together with the growth amount determined by the hero's rarity and the stat's GP, uniquely identifies the growth vector used by that stat. It is possible to infer missing entries from the complete stat tables as long as exactly one out of 64 variations correlates with the given entries, or even guess the vector ID if one or two of the given stats are incorrect.

Growth vector IDs change with the hero's IVs: (they warp around 00-63)

Hero Rarity Variation HP Atk Spd Def Res
Lyn: Brave Lady 5 Bane 23 20 33 58 27
Lyn: Brave Lady 5 Neutral 29 26 39 00 33
Lyn: Brave Lady 5 Boon 35 32 45 05 38

the hero's rarity:

Hero Rarity Variation HP Atk Spd Def Res
Olivia: Blushing Beauty 1 Neutral 41 20 38 31 35
Olivia: Blushing Beauty 2 Neutral 44 23 42 34 38
Olivia: Blushing Beauty 3 Neutral 48 27 47 38 42
Olivia: Blushing Beauty 4 Neutral 51 30 51 41 45
Olivia: Blushing Beauty 5 Neutral 54 34 55 45 49

and a single byte (hero_definition::base_vector_id) from the structs under Common/SRPG/Person that hold hero data:

Hero Rarity Variation BVID HP Atk Spd Def Res
Robin: High Deliverer 5 Neutral 43 15 53 60 03 56
Robin: Mystery Tactician 5 Neutral BF 11 49 56 63 52
Lucina: Future Witness 5 Neutral C2 22 02 15 57 46
Marth: Enigmatic Blade 5 Neutral 12 38 18 31 09 62

Deriving growth vector IDs[ | ]

Growth vector IDs can be calculated as the sum of the following terms, keeping only the 6 lowest bits (i.e. modulo 64):

  • 3 × (5-star level 1 neutral base stat);
  • A constant offset depending on the stat being calculated for, which increases "randomness":
HP Atk Spd Def Res
-35 -28 -21 -14 -7
  • The growth percentage corresponding to the Hero's rarity and the stat's GP;
  • The hero's base vector ID (hero_definition::base_vector_id). It is currently unknown if the highest 2 bits are computationally meaningful since the modulo operation discards them.

Brave Lyn's base vector ID is 0x9D. The growth vector IDs for her neutral stats can be computed as follows:

  • HP: (3 × 16 + (−35) + 51 + 157) mod 64 = 221 mod 64 = 29
  • Atk: (3 × 7 + (−28) + 68 + 157) mod 64 = 218 mod 64 = 26
  • Spd: (3 × 9 + (−21) + 68 + 157) mod 64 = 231 mod 64 = 39
  • Def: (3 × 5 + (−14) + 34 + 157) mod 64 = 192 mod 64 = 0
  • Res: (3 × 6 + (−7) + 57 + 157) mod 64 = 225 mod 64 = 33

This matches her vector IDs given at the top. This has been verified to match all pre-existing 5-star stat tables on this wiki.

Identical stat growths[ | ]

Due to the modulo operation it is theoretically possible that two completely different stats on the same hero use the same growth vector: (currently this is limited to HP/Atk base being 7 higher than Def/Res and GPs being the same)

Hero Stat A Base GP Stat B Base GP GVID Growth Vector
Chrom: Gifted Leader Atk Flaw 11 8 Res Asset 6 8 1 01100110 11000111 11100001 11110110 11111101
Tiki: Dragon Scion HP Flaw 14 7 Def Neutral 8 7 22 00101111 01111011 00111100 01010110 10111100
Tiki: Dragon Scion HP Neutral 15 8 Def Asset 9 8 28 01001001 11000111 10110011 11111101 11110110

Out-of-bound growth rates[ | ]

After rarity correction, if the growth rate is 0%, the stat uses a fixed growth vector, regardless of the Hero's base vector ID:

01100000 11001111 10111010 01100001 01110001

This is in fact the XOR cipher used for the growth vectors (see example code above). Because the growth vector files does not store empty vectors, it is possible that the game is accessing memory before the list of growth vectors; if it reads zeroes, the resulting growth vector is simply the XOR value itself. It is also possible that, depending on the Hero's base vector ID, the game may read the file's HSDArc header instead of zeroed memory.

If the growth rate is 100% or above, the integral part is applied to every level up, and the fractional part uses the growth vector mechanism as above. Growth rates can never be below 0%.

Advertisement