The Complete Damage Formula for Black & White

By Xfr, Bond697 and Kaphotics, with help from V4Victini. Art by Bummer.
  1. Introduction
  2. Main concepts
    1. General flow of damage calculation
    2. How to apply a modifier
    3. How to chain modifiers
    4. The multi-target modifier
    5. The weather modifier
    6. Critical hits
    7. The random factor
    8. STAB
    9. Type effectiveness
    10. Effect of a burn
    11. Final modifier
  3. The base power
    1. Triggers for variable base power
    2. Modifiers for the base power
  4. User attack stat
    1. Base value
    2. Boost level
    3. Attack modifiers
  5. Target defense stat
    1. Base value
    2. Boost level
    3. Sandstorm modifier
    4. Defense modifiers
  6. Special cases

Introduction

In Generation IV, the damage formula was derived empirically by X-Act from running it countless times, an approach that is both tedious and prone to errors. The good understanding of the ARM code for Black & White allows us to document the damage formula based on the actual source code of the game. It doesn't guarantee that we didn't make any mistake (interpreting assembly language is in itself a tricky task) but having the documented source along with the formula backs up our claims and allows anyone who spots any error to fix it by themselves.

Main concepts

General flow of damage calculation

  1. MEMORY:021C1E94 @ int __fastcall DamageCalc(void *trigger_table, void **attacking_bpkm, void **defending_bpkm, unsigned __int16 *move_id)
  2. MEMORY:021C1E94 DamageCalc:                             @ CODE XREF: MEMORY:021C0B28p
  3. MEMORY:021C1E94
  4. MEMORY:021C1E94 double_damage= -0x30
  5. MEMORY:021C1E94 p_attacking= -0x2C
  6. MEMORY:021C1E94 current_damage= -0x28
  7. MEMORY:021C1E94 static_damage= -0x24
  8. MEMORY:021C1E94 move_cat= -0x20
  9. MEMORY:021C1E94 base_power= -0x1C
  10. MEMORY:021C1E94 attack_stat= -0x18
  11. MEMORY:021C1E94 effectiveness_factor=  0
  12. MEMORY:021C1E94 field_mod=  4
  13. MEMORY:021C1E94 is_critical=  8
  14. MEMORY:021C1E94 rig_mindamage=  0xC
  15. MEMORY:021C1E94 p_store_result=  0x10
  16. MEMORY:021C1E94
  17. MEMORY:021C1E94 PUSH    {R4-R7,LR}
  18. MEMORY:021C1E96 SUB     SP, SP, #0x1C
  19. MEMORY:021C1E98 MOVS    R4, R3
  20. MEMORY:021C1E9A MOVS    R5, R0
  21. MEMORY:021C1E9C LDRH    R0, [R4]
  22. MEMORY:021C1E9E STR     R1, [SP,#0x30+p_attacking]
  23. MEMORY:021C1EA0 MOVS    R7, R2
  24. MEMORY:021C1EA2 LDR     R6, [SP,#0x30+is_critical]
  25. MEMORY:021C1EA4 BL      GetMoveCategory
  26. MEMORY:021C1EA8 STR     R0, [SP,#0x30+move_cat]
  27. MEMORY:021C1EAA MOVS    R0, #0
  28. MEMORY:021C1EAC STR     R0, [SP,#0x30+static_damage]
  29. MEMORY:021C1EAE LDR     R0, =0x1C21
  30. MEMORY:021C1EB0 BL      AllocateVolatileVariables
  31. MEMORY:021C1EB4 LDR     R1, [SP,#0x30+effectiveness_factor]
  32. MEMORY:021C1EB6 MOVS    R0, #0x38 @ '8'
  33. MEMORY:021C1EB8 BL      StoreVolatileVariableFlag3e4
  34. MEMORY:021C1EBC LDR     R0, [SP,#0x30+p_attacking]
  35. MEMORY:021C1EBE BL      Dereference25
  36. MEMORY:021C1EC2 MOVS    R1, R0
  37. MEMORY:021C1EC4 MOVS    R0, #3
  38. MEMORY:021C1EC6 BL      StoreVolatileVariableFlag3e4
  39. MEMORY:021C1ECA MOVS    R0, R7
  40. MEMORY:021C1ECC BL      Dereference25
  41. MEMORY:021C1ED0 MOVS    R1, R0
  42. MEMORY:021C1ED2 MOVS    R0, #4
  43. MEMORY:021C1ED4 BL      StoreVolatileVariableFlag3e4
  44. MEMORY:021C1ED8 MOVS    R0, #0x45 @ 'E'
  45. MEMORY:021C1EDA MOVS    R1, R6
  46. MEMORY:021C1EDC BL      StoreVolatileVariableFlag3e4
  47. MEMORY:021C1EE0 LDRB    R1, [R4,#6]
  48. MEMORY:021C1EE2 MOVS    R0, #0x16
  49. MEMORY:021C1EE4 BL      StoreVolatileVariableFlag3e4
  50. MEMORY:021C1EE8 LDRH    R1, [R4]
  51. MEMORY:021C1EEA MOVS    R0, #0x12
  52. MEMORY:021C1EEC BL      StoreVolatileVariableFlag3e4
  53. MEMORY:021C1EF0 LDR     R1, [SP,#0x30+move_cat]
  54. MEMORY:021C1EF2 MOVS    R0, #0x1A
  55. MEMORY:021C1EF4 BL      StoreVolatileVariableFlag3e4
  56. MEMORY:021C1EF8 MOVS    R0, #0x37 @ '7'
  57. MEMORY:021C1EFA MOVS    R1, #0
  58. MEMORY:021C1EFC BL      InitVolatileVariable
  59. MEMORY:021C1F00 MOVS    R0, R5
  60. MEMORY:021C1F02 MOVS    R1, #0x46 @ 'F'
  61. MEMORY:021C1F04 BL      ApplyTriggers
  62. MEMORY:021C1F08 MOVS    R0, #0x37 @ '7'
  63. MEMORY:021C1F0A BL      ReadVolatileVariable
  64. MEMORY:021C1F0E STR     R0, [SP,#0x30+current_damage]
  65. MEMORY:021C1F10 CMP     R0, #0
  66. MEMORY:021C1F12 BEQ     Bank0
  67. MEMORY:021C1F14 MOVS    R0, #1
  68. MEMORY:021C1F16 STR     R0, [SP,#0x30+static_damage]
  69. MEMORY:021C1F18 B       Bank9
  70. MEMORY:021C1F1A @ ---------------------------------------------------------------------------
  71. MEMORY:021C1F1A
  72. MEMORY:021C1F1A Bank0:                                  @ CODE XREF: DamageCalc+7Ej
  73. MEMORY:021C1F1A LDR     R1, [SP,#0x30+p_attacking]
  74. MEMORY:021C1F1C MOVS    R0, R5
  75. MEMORY:021C1F1E MOVS    R2, R7
  76. MEMORY:021C1F20 MOVS    R3, R4
  77. MEMORY:021C1F22 BL      BasePowerMods
  78. MEMORY:021C1F26 STR     R0, [SP,#0x30+base_power]
  79. MEMORY:021C1F28 LDR     R1, [SP,#0x30+p_attacking]
  80. MEMORY:021C1F2A MOVS    R0, R5
  81. MEMORY:021C1F2C MOVS    R2, R7
  82. MEMORY:021C1F2E MOVS    R3, R4
  83. MEMORY:021C1F30 STR     R6, [SP,#0x30+double_damage]
  84. MEMORY:021C1F32 BL      BaseAttackMods
  85. MEMORY:021C1F36 STR     R0, [SP,#0x30+attack_stat]
  86. MEMORY:021C1F38 LDR     R1, [SP,#0x30+p_attacking]
  87. MEMORY:021C1F3A MOVS    R0, R5
  88. MEMORY:021C1F3C MOVS    R2, R7
  89. MEMORY:021C1F3E MOVS    R3, R4
  90. MEMORY:021C1F40 STR     R6, [SP,#0x30+double_damage]
  91. MEMORY:021C1F42 BL      BaseDefenseMods
  92. MEMORY:021C1F46 MOVS    R7, R0
  93. MEMORY:021C1F48 LDR     R0, [SP,#0x30+p_attacking]
  94. MEMORY:021C1F4A MOVS    R1, #0xF
  95. MEMORY:021C1F4C BL      GetBpkmStat
  96. MEMORY:021C1F50 LSLS    R0, R0, #0x18
  97. MEMORY:021C1F52 LSRS    R2, R0, #0x18
  98. MEMORY:021C1F54 LDR     R0, [SP,#0x30+base_power]
  99. MEMORY:021C1F56 LDR     R1, [SP,#0x30+attack_stat]
  100. MEMORY:021C1F58 MOVS    R3, R7
  101. MEMORY:021C1F5A BL      BaseDamageFormula
  102. MEMORY:021C1F5E MOVS    R2, #4
  103. MEMORY:021C1F60 LDR     R1, [SP,#0x30+field_mod]
  104. MEMORY:021C1F62 LSLS    R2, R2, #0xA
  105. MEMORY:021C1F64 MOVS    R7, R0
  106. MEMORY:021C1F66 CMP     R1, R2
  107. MEMORY:021C1F68 BEQ     Bank1
  108. MEMORY:021C1F6A BL      ApplyMod
  109. MEMORY:021C1F6E ADDS    R7, R0, #0
  110. MEMORY:021C1F70
  111. MEMORY:021C1F70 Bank1:                                  @ CODE XREF: DamageCalc+D4j
  112. MEMORY:021C1F70 MOVS    R0, R5
  113. MEMORY:021C1F72 BL      WeatherTriggers
  114. MEMORY:021C1F76 LDRB    R1, [R4,#6]
  115. MEMORY:021C1F78 BL      WeatherMod
  116. MEMORY:021C1F7C MOVS    R1, R0
  117. MEMORY:021C1F7E MOVS    R0, 0x1000
  118. MEMORY:021C1F82 CMP     R1, R0
  119. MEMORY:021C1F84 BEQ     Bank2
  120. MEMORY:021C1F86 MOVS    R0, R7
  121. MEMORY:021C1F88 BL      ApplyMod
  122. MEMORY:021C1F8C ADDS    R7, R0, #0
  123. MEMORY:021C1F8E
  124. MEMORY:021C1F8E Bank2:                                  @ CODE XREF: DamageCalc+F0j
  125. MEMORY:021C1F8E CMP     R6, #0
  126. MEMORY:021C1F90 BEQ     Bank3
  127. MEMORY:021C1F92 LSLS    R7, R7, #1
  128. MEMORY:021C1F94
  129. MEMORY:021C1F94 Bank3:                                  @ CODE XREF: DamageCalc+FCj
  130. MEMORY:021C1F94 LDR     R0, [R5,#4]
  131. MEMORY:021C1F96 MOVS    R1, #7
  132. MEMORY:021C1F98 BL      sub_21B913C
  133. MEMORY:021C1F9C CMP     R0, #0
  134. MEMORY:021C1F9E BNE     Bank6
  135. MEMORY:021C1FA0 LDR     R0, [SP,#0x30+rig_mindamage]
  136. MEMORY:021C1FA2 CMP     R0, #0
  137. MEMORY:021C1FA4 BEQ     Bank4
  138. MEMORY:021C1FA6 MOVS    R0, #0x55 @ 'U'
  139. MEMORY:021C1FA8 B       Bank5
  140. MEMORY:021C1FAA @ ---------------------------------------------------------------------------
  141. MEMORY:021C1FAA
  142. MEMORY:021C1FAA Bank4:                                  @ CODE XREF: DamageCalc+110j
  143. MEMORY:021C1FAA MOVS    R0, #0x10
  144. MEMORY:021C1FAC BL      BRand
  145. MEMORY:021C1FB0 MOVS    R1, #0x64 @ 'd'
  146. MEMORY:021C1FB2 SUBS    R0, R1, R0
  147. MEMORY:021C1FB4 LSLS    R0, R0, #0x10
  148. MEMORY:021C1FB6 LSRS    R0, R0, #0x10
  149. MEMORY:021C1FB8
  150. MEMORY:021C1FB8 Bank5:                                  @ CODE XREF: DamageCalc+114j
  151. MEMORY:021C1FB8 MULS    R0, R7
  152. MEMORY:021C1FBA MOVS    R1, #0x64 @ 'd'                 @ divisor
  153. MEMORY:021C1FBC BLX     divmodUnsigned__
  154. MEMORY:021C1FC0 ADDS    R7, R0, #0
  155. MEMORY:021C1FC2
  156. MEMORY:021C1FC2 Bank6:                                  @ CODE XREF: DamageCalc+10Aj
  157. MEMORY:021C1FC2 LDRB    R2, [R4,#6]
  158. MEMORY:021C1FC4 CMP     R2, #0x11
  159. MEMORY:021C1FC6 BEQ     Bank7
  160. MEMORY:021C1FC8 LDR     R1, [SP,#0x30+p_attacking]
  161. MEMORY:021C1FCA ADDS    R0, R5, #0
  162. MEMORY:021C1FCC
  163. MEMORY:021C1FCC Bank_STAB:                              @ CODE XREF: MEMORY:021C1D6Aj
  164. MEMORY:021C1FCC BL      STAB
  165. MEMORY:021C1FD0 MOVS    R1, R0
  166. MEMORY:021C1FD2 MOVS    R0, R7
  167. MEMORY:021C1FD4 BL      ApplyMod
  168. MEMORY:021C1FD8 ADDS    R7, R0, #0
  169. MEMORY:021C1FDA
  170. MEMORY:021C1FDA Bank7:                                  @ CODE XREF: DamageCalc+132j
  171. MEMORY:021C1FDA LDR     R1, [SP,#0x30+effectiveness_factor]
  172. MEMORY:021C1FDC
  173. MEMORY:021C1FDC loc_21C1FDC:                            @ CODE XREF: MEMORY:021C1D7Aj
  174. MEMORY:021C1FDC MOVS    R0, R7
  175. MEMORY:021C1FDE BL      TypeEffectiveness
  176. MEMORY:021C1FE2 MOVS    R4, R0
  177. MEMORY:021C1FE4 LDR     R0, [SP,#0x30+move_cat]
  178. MEMORY:021C1FE6 CMP     R0, #1
  179. MEMORY:021C1FE8 BNE     Bank_notnull
  180. MEMORY:021C1FEA LDR     R0, [SP,#0x30+p_attacking]
  181. MEMORY:021C1FEC BL      GetBpkmStatus
  182. MEMORY:021C1FF0 CMP     R0, #4
  183. MEMORY:021C1FF2 BNE     Bank_notnull
  184. MEMORY:021C1FF4 LDR     R0, [SP,#0x30+p_attacking]
  185. MEMORY:021C1FF6 MOVS    R1, #0x11
  186. MEMORY:021C1FF8 BL      GetBpkmStat
  187. MEMORY:021C1FFC CMP     R0, #0x3E @ '>'
  188. MEMORY:021C1FFE BEQ     Bank_notnull
  189. MEMORY:021C2000 MOVS    R0, #0x32 @ '2'
  190. MEMORY:021C2002 MULS    R0, R4
  191. MEMORY:021C2004 MOVS    R1, #0x64 @ 'd'                 @ divisor
  192. MEMORY:021C2006 BLX     divmodUnsigned__
  193. MEMORY:021C200A ADDS    R4, R0, #0
  194. MEMORY:021C200C
  195. MEMORY:021C200C Bank_notnull:                           @ CODE XREF: DamageCalc+154j
  196. MEMORY:021C200C                                         @ DamageCalc+15Ej ...
  197. MEMORY:021C200C CMP     R4, #0
  198. MEMORY:021C200E BNE     Bank8
  199. MEMORY:021C2010 MOVS    R4, #1
  200. MEMORY:021C2012
  201. MEMORY:021C2012 Bank8:                                  @ CODE XREF: DamageCalc+17Aj
  202. MEMORY:021C2012 MOVS    R1, 0x1000
  203. MEMORY:021C2016 MOVS    R0, #0x35 @ '5'
  204. MEMORY:021C2018 MOVS    R2, #0x29 @ ')'
  205. MEMORY:021C201A LSLS    R3, R1, #5
  206. MEMORY:021C201C BL      StoreVolatileVariableFlag3e3
  207. MEMORY:021C2020 MOVS    R0, #0x32 @ '2'
  208. MEMORY:021C2022 MOVS    R1, R4
  209. MEMORY:021C2024 BL      InitVolatileVariable
  210. MEMORY:021C2028 MOVS    R0, R5
  211. MEMORY:021C202A MOVS    R1, #0x47 @ 'G'
  212. MEMORY:021C202C BL      ApplyTriggers
  213. MEMORY:021C2030 MOVS    R0, #0x35 @ '5'
  214. MEMORY:021C2032 BL      ReadVolatileVariable
  215. MEMORY:021C2036 MOVS    R4, R0
  216. MEMORY:021C2038 MOVS    R0, #0x32 @ '2'
  217. MEMORY:021C203A BL      ReadVolatileVariable
  218. MEMORY:021C203E MOVS    R1, R4
  219. MEMORY:021C2040 BL      ApplyMod
  220. MEMORY:021C2044 STR     R0, [SP,#0x30+current_damage]
  221. MEMORY:021C2046
  222. MEMORY:021C2046 Bank9:                                  @ CODE XREF: DamageCalc+84j
  223. MEMORY:021C2046 MOVS    R0, R5
  224. MEMORY:021C2048 MOVS    R1, #0x48 @ 'H'
  225. MEMORY:021C204A BL      ApplyTriggers
  226. MEMORY:021C204E LDR     R0, =0x1C8D
  227. MEMORY:021C2050 BL      FreeVolatileVariable
  228. MEMORY:021C2054 LDR     R1, [SP,#0x30+p_store_result]
  229. MEMORY:021C2056 LDR     R0, [SP,#0x30+current_damage]
  230. MEMORY:021C2058 STRH    R0, [R1]
  231. MEMORY:021C205A LDR     R0, [SP,#0x30+static_damage]
  232. MEMORY:021C205C ADD     SP, SP, #0x1C
  233. MEMORY:021C205E POP     {R4-R7,PC}
  234. MEMORY:021C205E @ End of function DamageCalc
  235.  

Roughly speaking, the damage formula in Pokémon is a big multiplication, each factor representing the user's level and attack stat, the foe's defense stat, and a bunch of factors for STAB, held items, abilities and other field effects. In a perfect world where ARM CPUs could work on real numbers, it would be possible to multiply each factor in any order and get the same result, but in practice the game will round some multiplications and truncate others, meaning that in order to get accurate damage results, it is of utmost importance to perform the multiplication in the same order as the game and using the same rounding methods. Even though rounding errors might not sound like a big problem, they will be amplified at each step, and a few factors such as Reflect and Life Orb in a double battle can cause a significant difference between an unrounded and a properly rounded calculation.

There are three main parameters for damage calculation: the user's attack stat, the target's defense stat and the move's base power. To compute these stats, the game starts from a base value and apply a modifier to reflect the various effects that can alter the base value. This modifier is obtained by running through a list of short functions called triggers that are called based on the current active effects on field. Different triggers can modify the same modifier before it is applied, this operation is called chaining and is explained below.

Once the main parameters are set, the general steps of the calculation are as follows:

BaseDamage = ((((2 × Level) ÷ 5 + 2) * BasePower * [Sp]Atk) ÷ [Sp]Def) ÷ 50 + 2

  1. Apply the multi-target modifier
  2. Apply the weather modifier
  3. In case of a critical hit, double the value
  4. Alter with a random factor
  5. Apply STAB modifier
  6. Alter with type effectiveness
  7. Alter with user's burn
  8. Make sure damage is at least 1
  9. Apply the final modifier

In this article, ÷ always denotes the in-game unsigned divmod function, i.e. the unrounded/truncated integer division. By contrast, "apply a modifier" is a rounded operation explained in the next subsection.

There are some exceptions to the formula above that correspond to the set of triggers at the very top of the damage function; they are detailed in a separate section.

How to apply a modifier

  1. MEMORY:021D7B30 @ int __fastcall ApplyMod(int base_value, int modifier)
  2. MEMORY:021D7B30 ApplyMod:                               @ CODE XREF: sub_21BC968+68p
  3. MEMORY:021D7B30 MULS    R1, R0
  4. MEMORY:021D7B32 LDR     R0, =0xFFF
  5. MEMORY:021D7B34 MOVS    R2, R1
  6. MEMORY:021D7B36 ANDS    R2, R0
  7. MEMORY:021D7B38 LSRS    R0, R1, #0xC
  8. MEMORY:021D7B3A MOVS    R1, 0x800
  9. MEMORY:021D7B3E CMP     R2, R1
  10. MEMORY:021D7B40 BLS     locret_21D7B44
  11. MEMORY:021D7B42 ADDS    R0, R0, #1

A modifier is a 16 bit fixed point factor, i.e. a fraction whose divisor is always 0x1000 (4096). For instance, 0x14cc is the modifier for Life Orb (0x14cc/0x1000 is about 1.3). Applying the modifier M to the damage value D means multiplying D by M and dividing the result by 0x1000; then if the decimal part is ≤0.5, round the result down, otherwise round it up. Simply put: D' = round(D * M / 0x1000)

How to chain modifiers

  1. MEMORY:021D7724 @ void __fastcall ChainMod(__int16 Volatile_index, int mod)
  2. MEMORY:021D7724 ChainMod:                               @ CODE XREF: AccuracyCheck+FAp
  3. MEMORY:021D7724                                         @ MEMORY:021D8B5Ep ...
  4. MEMORY:021D7724 PUSH    {R3-R7,LR}
  5. MEMORY:021D7726 MOVS    R2, R0
  6. MEMORY:021D7728 MOVS    R7, R1
  7. MEMORY:021D772A LDR     R0, =VolatileStore
  8. MEMORY:021D772C MOVS    R1, R2
  9. MEMORY:021D772E BL      sub_21D7808
  10. MEMORY:021D7732 MOVS    R5, R0
  11. MEMORY:021D7734 BMI     locret_21D7772
  12. MEMORY:021D7736 LDR     R0, =VolatileStore
  13. MEMORY:021D7738 ADDS    R1, R0, R5
  14. MEMORY:021D773A LDR     R0, =0x544
  15. MEMORY:021D773C LDRB    R0, [R1,R0]
  16. MEMORY:021D773E CMP     R0, #3
  17. MEMORY:021D7740 BNE     locret_21D7772
  18. MEMORY:021D7742 LDR     R4, =VolatileStore
  19. MEMORY:021D7744 LSLS    R6, R5, #2
  20. MEMORY:021D7746 ADDS    R4, #0xC4 @ '-'
  21. MEMORY:021D7748 LDR     R0, [R4,R6]                     @ num1
  22. MEMORY:021D774A ASRS    R3, R7, #0x1F
  23. MEMORY:021D774C ASRS    R1, R0, #0x1F
  24. MEMORY:021D774E MOVS    R2, R7                          @ num2
  25. MEMORY:021D7750 BLX     mul64Unsigned__
  26. MEMORY:021D7754 MOVS    R3, R1
  27. MEMORY:021D7756 MOVS    R1, R5
  28. MEMORY:021D7758 MOVS    R5, #2
  29. MEMORY:021D775A MOVS    R2, R0
  30. MEMORY:021D775C MOVS    R7, #0
  31. MEMORY:021D775E LSLS    R5, R5, #0xA
  32. MEMORY:021D7760 ADDS    R2, R2, R5
  33. MEMORY:021D7762 ADCS    R3, R7
  34. MEMORY:021D7764 LDR     R0, =VolatileStore
  35. MEMORY:021D7766 LSLS    R3, R3, #0x14
  36. MEMORY:021D7768 LSRS    R2, R2, #0xC
  37. MEMORY:021D776A ORRS    R2, R3
  38. MEMORY:021D776C BL      sub_21D782C
  39. MEMORY:021D7770 STR     R0, [R4,R6]

Recall that modifiers for a given parameters are computed by the triggers for that parameter. This means that when multiple triggers apply, you have to chain the modifier for the parameter, starting from 0x1000. If the current modifier is M and you want to chain with another modifier M', the resulting modifier would be: M'' = ((M * M') + 0x800) >> 12

The multi-target modifier

  1. MEMORY:021C0DCC @ ---------------------------------------------------------------------------
  2. MEMORY:021C0DBE BL      sub_21C0EE4
  3. MEMORY:021C0DC2 CMP     R0, #1
  4. MEMORY:021C0DC4 BNE     loc_21C0DCC
  5. MEMORY:021C0DC6 MOVS    R4, 0x1000
  6. MEMORY:021C0DCA B       loc_21C0DD0
  7. MEMORY:021C0DCC @ ---------------------------------------------------------------------------
  8. MEMORY:021C0DCC loc_21C0DCC:
  9. MEMORY:021C0DCC MOVS    R4, 0xC00

This modifier doesn't have any trigger and is set to 0xC00 if the move has more than one target and 0x1000 otherwise. Being a target is independent of all accuracy and effectiveness checks, but a fainted Pokémon on the field will not count as a target.

The weather modifier

  1. MEMORY:021D7C58 @ int __fastcall WeatherMod(__int16 active_weather)
  2. MEMORY:021D7C58 WeatherMod:                             @ CODE XREF: DamageCalc+E4p
  3. MEMORY:021D7C58 CMP     R0, #1
  4. MEMORY:021D7C5A BEQ     loc_21D7C62
  5. MEMORY:021D7C5C CMP     R0, #2
  6. MEMORY:021D7C5E BEQ     loc_21D7C76
  7. MEMORY:021D7C60 B       loc_21D7C8A
  8. MEMORY:021D7C62 @ ---------------------------------------------------------------------------
  9. MEMORY:021D7C62
  10. MEMORY:021D7C62 loc_21D7C62:                            @ CODE XREF: WeatherMod+2j
  11. MEMORY:021D7C62 CMP     R1, #9
  12. MEMORY:021D7C64 BNE     loc_21D7C6C
  13. MEMORY:021D7C66 MOVS    R0, 0x1800
  14. MEMORY:021D7C6A BX      LR
  15. MEMORY:021D7C6C @ ---------------------------------------------------------------------------
  16. MEMORY:021D7C6C
  17. MEMORY:021D7C6C loc_21D7C6C:                            @ CODE XREF: WeatherMod+Cj
  18. MEMORY:021D7C6C CMP     R1, #0xA
  19. MEMORY:021D7C6E BNE     loc_21D7C8A
  20. MEMORY:021D7C70 MOVS    R0, 0x800
  21. MEMORY:021D7C74 BX      LR
  22. MEMORY:021D7C76 @ ---------------------------------------------------------------------------
  23. MEMORY:021D7C76
  24. MEMORY:021D7C76 loc_21D7C76:                            @ CODE XREF: WeatherMod+6j
  25. MEMORY:021D7C76 CMP     R1, #9
  26. MEMORY:021D7C78 BNE     loc_21D7C80
  27. MEMORY:021D7C7A MOVS    R0, 0x800
  28. MEMORY:021D7C7E BX      LR
  29. MEMORY:021D7C80 @ ---------------------------------------------------------------------------
  30. MEMORY:021D7C80
  31. MEMORY:021D7C80 loc_21D7C80:                            @ CODE XREF: WeatherMod+20j
  32. MEMORY:021D7C80 CMP     R1, #0xA
  33. MEMORY:021D7C82 BNE     loc_21D7C8A
  34. MEMORY:021D7C84 MOVS    R0, 0x1800
  35. MEMORY:021D7C88 BX      LR
  36. MEMORY:021D7C8A @ ---------------------------------------------------------------------------
  37. MEMORY:021D7C8A
  38. MEMORY:021D7C8A loc_21D7C8A:                            @ CODE XREF: WeatherMod+8j
  39. MEMORY:021D7C8A                                         @ WeatherMod+16j ...
  40. MEMORY:021D7C8A MOVS    R0, 0x1000
  41. MEMORY:021D7C8E BX      LR

Even though the weather modifier has its own set of triggers listed below, they never affect the actual value of the modifier: a water move used during rain or a fire move used during intense sunlight will use 0x1800 as modifier, while a fire move used during rain or a water move during intense sunlight will use 0x800.

Trigger address Trigger description
21d9850 Cancel weather if any Pokémon on field has Air Lock or Cloud Nine.
21d9084 Internal.

Critical hits

Trigger address Trigger description
21d9be8 Super Luck: increase user's critical hit level by 1.
21d9bc4 Battle Armor / Shell Armor: if the target has either of these abilities, bypass critical hit checks.
21dae18 Internal.
21de5fc Stick: if user is Farfetch'd and holds Stick, increase critical hit level by 2.
21de5b8 Lucky Punch: if user is Chansey and holds Lucky Punch, increase critical hit level by 2.
21de584 Razor Claw: increase holder's critical hit level by 1.
21e53b4 Internal.
6899210 Lucky Chant: if the user's party is protected by Lucky Chant, bypass critical hit checks.

The random factor

Provided the battle isn't rigged to always use minimum damage, the current damage value D is altered using a random number 0 ≤ R ≤ 15:

D' = (D * (100-R)) ÷ 100

STAB

  1. MEMORY:021C760C STAB:                                   @ CODE XREF: DamageCalc:Bank_STABp
  2. MEMORY:021C760C PUSH    {R3-R7,LR}
  3. MEMORY:021C760E MOVS    R7, R1
  4. MEMORY:021C7610 MOVS    R5, R0
  5. MEMORY:021C7612 MOVS    R0, R7
  6. MEMORY:021C7614 MOVS    R1, R2
  7. MEMORY:021C7616 BL      IsMoveOfUserType
  8. MEMORY:021C761A MOVS    R6, R0
  9. MEMORY:021C761C MOVS    R4, #1
  10. MEMORY:021C761E LDR     R0, =0x3178
  11. MEMORY:021C7620 LSLS    R4, R4, #0xC
  12. MEMORY:021C7622 BL      AllocateVolatileVariables
  13. MEMORY:021C7626 MOVS    R0, R7
  14. MEMORY:021C7628 BL      Dereference25
  15. MEMORY:021C762C MOVS    R1, R0
  16. MEMORY:021C762E MOVS    R0, #2
  17. MEMORY:021C7630 BL      StoreVolatileVariableFlag3e4
  18. MEMORY:021C7634 MOVS    R0, #0x51 @ 'Q'
  19. MEMORY:021C7636 MOVS    R1, R6
  20. MEMORY:021C7638 BL      StoreVolatileVariableFlag3e1
  21. MEMORY:021C763C MOVS    R0, R5
  22. MEMORY:021C763E MOVS    R1, #0x40 @ '@'
  23. MEMORY:021C7640 BL      ApplyTriggers
  24. MEMORY:021C7644 MOVS    R0, #0x51 @ 'Q'
  25. MEMORY:021C7646 BL      ReadVolatileVariable
  26. MEMORY:021C764A MOVS    R1, R0
  27. MEMORY:021C764C BEQ     loc_21C7652
  28. MEMORY:021C764E MOVS    R4, 0x1800
  29. MEMORY:021C7652
  30. MEMORY:021C7652 loc_21C7652:                            @ CODE XREF: STAB+40j
  31. MEMORY:021C7652 MOVS    R0, #0x44 @ 'D'
  32. MEMORY:021C7654 BL      StoreVolatileVariableFlag3e4
  33. MEMORY:021C7658 MOVS    R0, #0x35 @ '5'
  34. MEMORY:021C765A MOVS    R1, R4
  35. MEMORY:021C765C BL      InitVolatileVariable
  36. MEMORY:021C7660 MOVS    R0, R5
  37. MEMORY:021C7662 MOVS    R1, #0x41 @ 'A'
  38. MEMORY:021C7664 BL      ApplyTriggers
  39. MEMORY:021C7668 MOVS    R0, #0x35 @ '5'
  40. MEMORY:021C766A BL      ReadVolatileVariable
  41. MEMORY:021C766E MOVS    R4, R0
  42. MEMORY:021C7670 LDR     R0, =0x3189
  43. MEMORY:021C7672 BL      FreeVolatileVariable
  44. MEMORY:021C7676 MOVS    R0, R4
  45. MEMORY:021C7678 POP     {R3-R7,PC}
  46. MEMORY:021C7678 @ End of function STAB

If the type of the move match one of its users', the STAB modifier is set to 0x1800. The only trigger for this modifier is listed below.

Trigger address Trigger description
21D8C2D Adaptability: if the user has this ability and move matches one of the user's types, the initial value for the final modifier is set to 0x2000.

Type effectiveness

  1. MEMORY:021D7A8C TypeEffectiveness:                      @ CODE XREF: DamageCalc+14Ap
  2. MEMORY:021D7A8C CMP     R1, #5
  3. MEMORY:021D7A8E BHI     locret_21D7ABA
  4. MEMORY:021D7A90 ADDS    R1, R1, R1
  5. MEMORY:021D7A92 ADD     R1, PC
  6. MEMORY:021D7A94 LDRH    R1, [R1,#6]
  7. MEMORY:021D7A96 LSLS    R1, R1, #0x10
  8. MEMORY:021D7A98 ASRS    R1, R1, #0x10
  9. MEMORY:021D7A9A ADD     PC, R1
  10. MEMORY:021D7A9A @ ---------------------------------------------------------------------------
  11. MEMORY:021D7A9C .byte  0xA
  12. MEMORY:021D7A9D .byte    0
  13. MEMORY:021D7A9E .byte  0xE
  14. MEMORY:021D7A9F .byte    0
  15. MEMORY:021D7AA0 .byte 0x12
  16. MEMORY:021D7AA1 .byte    0
  17. MEMORY:021D7AA2 .byte 0x14
  18. MEMORY:021D7AA3 .byte    0
  19. MEMORY:021D7AA4 .byte 0x16
  20. MEMORY:021D7AA5 .byte    0
  21. MEMORY:021D7AA6 .byte 0x1A
  22. MEMORY:021D7AA7 .byte    0
  23. MEMORY:021D7AA8 @ ---------------------------------------------------------------------------
  24. MEMORY:021D7AA8 MOVS    R0, #0
  25. MEMORY:021D7AAA BX      LR
  26. MEMORY:021D7AAC @ ---------------------------------------------------------------------------
  27. MEMORY:021D7AAC LSRS    R0, R0, #2
  28. MEMORY:021D7AAE BX      LR
  29. MEMORY:021D7AB0 @ ---------------------------------------------------------------------------
  30. MEMORY:021D7AB0 LSRS    R0, R0, #1
  31. MEMORY:021D7AB2 BX      LR
  32. MEMORY:021D7AB4 @ ---------------------------------------------------------------------------
  33. MEMORY:021D7AB4 LSLS    R0, R0, #1
  34. MEMORY:021D7AB6 BX      LR
  35. MEMORY:021D7AB8 @ ---------------------------------------------------------------------------
  36. MEMORY:021D7AB8 LSLS    R0, R0, #2
  37. MEMORY:021D7ABA
  38. MEMORY:021D7ABA locret_21D7ABA:                         @ CODE XREF: TypeEffectiveness+2j
  39. MEMORY:021D7ABA BX      LR

Type effectiveness doesn't use a modifier but a simple left (respectively right) shift of one for a simple and two for a double weakness (respectively resistance), in other words an unrounded division or multiplication by 2 or 4.

Effect of a burn

The effect of a burn is directly taken into account in the damage formula. First, the game checks if the attack is physical, then if the user is burned, and finally if its ability is different than Guts. If all conditions are satisfied, the current damage is divided by 2 with no rounding.

Final modifier

The final modifier is decided by calling the appropriate triggers, which are listed below. Be sure to chain the modifiers in the order they are listed in.
Trigger address Modifier Trigger description
6898E29 Variable If the target's side is affected by Reflect, the move used was physical, the user's ability isn't Infiltrator and the critical hit flag isn't set.
The value of the modificator is 0xA8F if there is more than one Pokémon per side of the field and 0x800 otherwise.
6898E45 Variable Same as above with Light Screen and special moves.
21DC125 0x800 If the target's ability is Multiscale and the target is at full health.
21D8B3D 0x2000 If the user's ability is Tinted Lens and the move wasn't very effective.
21DC15D 0xC00 If one of the target's allies' ability is Friend Guard.
21D8BA5 0x1800 If user has ability Sniper and move was a critical hit.
21D8B71 0xC00 If the target's ability is Solid Rock or Filter and the move was super effective.
21DBA95 Internal.
21DEC91 Variable If the user is holding the item Metronome. If n is the number of time the current move was used successfully and successively, the value of the modifier is 0x1000+n*0x333 if n≤4 and 0x2000 otherwise.
21DEBD5 0x1333 If the user is holding an expert belt and the move was super effective.
21DEC65 0x14CC If the user is holding a Life Orb.
21DDB85 0x800 If the target is holding a damage lowering berry of the attack's type. There is one trigger for each type of berry, the others are at:
21DDC05, 21DDAE5, 21DDB05, 21DDB25, 21DDB45, 21DDB65, 21DDBA5, 21DDBC5, 21DDBE5, 21DDC25, 21DDC45, 21DDC65, 21DDC85, 21DDCA5, 21DDCC5 and 21DDCE5.
21E3A25 0x2000 If move is Stomp and target has used Minimize.
21E316D 0x2000 If move is Earthquake and target is in the charging turn of Dig.
21E39E1 0x2000 If move is Surf and target is in the charging turn of Dive.
21E1455 0x2000 If move is Steamroller and target has used Minimize.

The base power

There are two separate sets of triggers for the base power of moves. The first is mainly used for moves with a variable base power, while the second contains the various modifiers for base power.

Triggers for variable base power

Trigger address Summary of BP formula Move and remarks.
21d88cc Internal.
21e2aec ((255 - Happiness) * 10) ÷ 25 Frustration: if result is 0 add 1.
21e2968 50, 100 Payback: BP is doubled to 100 if target has moved this turn, 50 otherwise.
21e2aa0 (Happiness * 10) ÷ 25 Return: if result is 0 add 1.
21e7184 150, 120, 80, 60, 40 Electro Ball: Let S = UserModSpeed ÷ TargetModSpeed. BP = {150: S ≥ 4, 120: 3 ≤ S < 4, 80: 2 ≤ S < 3, 60: 1 ≤ S < 2, 40: otherwise};
21e283c 60, 120 Avalanche: BP is doubled to 120 if the target has inflicted non-effect damage to the user this turn.
21e27d0 min(150, 25 * TargetSpd ÷ UserSpd) Gyro Ball.
21e29a8 (150 * CurrentHP) ÷ MaxHP Eruption, Water Spout: if result is 0 set BP to 1.
21e2de0 min(120, 60 + 20 * statup_total) Punishment: statup_total is the sum of the target's stat levels that are ≥ 0, including accuracy and evasion.
21e2e48 20 * 2^(use_counter) Fury Cutter: use_counter counts successive and successful previous uses up to a maximum of 3.
21e2ef4 20, 40, 60, 80, 100, 120 Low Kick, Grass Knot: let W be the final weight after modifiers. If W ≥ 200, BP is 120, else if W ≥ 100, BP is 100, else if W ≥ 50, BP is 80, else if W ≥ 25, BP is 60, else if W ≥ 10, BP is 40, else BP is 20.
21e7204 40, 80, 120, 160, 200 Echoed Voice: BP increases in the listed order every turn this move is used successively on the user's side of the field.
21e702c 50, 100 Hex: BP is doubled to 100 if target has a status problem.
21e2a08 round(120 * TargetHP%) ÷ 100 Wring Out, Crush Grip: TargetHP% is computed by a fixed point division using 0x1000 as the scaling factor.
21e2eb0 50, 100 Assurance: BP is doubled to 100 if target has already been inflicted non-effect damage this turn.
21e7104 120, 100, 80, 60, 40 Heavy Slam, Heat Crash: let W = UserModWeight ÷ TargetModWeight. BP = {120: W ≥ 5, 100: 4 ≤ W < 5, 80: 3 ≤ W < 4, 60: 2 ≤ W < 3, 40: W < 2}.
21e70a0 20 + 20 * statups Stored Power: statups is the sum of all positive stat increases, including accuracy and evasion.
21e706c 55, 110 Acrobatics: BP is doubled to 110 if user has no held item.
21e28b8 P = (48 * CurrentHP) ÷ MaxHP Flail, Reversal: 200 if P ≤ 1, 150 if 2 ≤ P ≤ 4, 100 if 5 ≤ P ≤ 9, 80 if 10 ≤ P ≤ 16, 40 if 17 ≤ P ≤ 32, 20 otherwise.
21e2d7c 40, 50, 60, 80, 200 Trump Card: listed BP correspond to decreasing PP (if PP is ≥ 5 or this move was called by another move BP is 40).
21e7dd0 60, 120 Round: BP is doubled to 120 if used in direct succession of an ally.
21e2788 10, 20, 30 Triple Kick: BP is listed for the successive hits.
21e2b38 60, 120 Wake-Up Slap: BP is doubled to 120 if target is asleep.
21e2bd4 60, 120 SmellingSalt: BP is doubled to 120 is target is paralyzed.
21e2fd0 50, 100 Weather Ball: BP is doubled to 100 in any non-default weather.
21e302c 40, 80 Gust, Twister: BP is doubled to 80 is target is in the charging turn of Bounce, Fly or Sky Drop.
21e6074 CurrentPartyMemberAttack ÷ 10 + 5 Beat Up: this move attacks once for every non fainted member in the user's party, including the user.
21e3318 30 + (40 * sum(((IV[i]>>1)&1)<<i)) ÷ 63 Hidden Power: IV are indexed from 0 and listed as HP, At, Df, Sp, SA, SD.
21e17d0 100 * stockpile Spit Up: stockpile is the stockpile counter ranging from 0 to 3.
21e1dbc 40, 80 Pursuit: BP is doubled to 80 if target is switching out.
21e2d40 40, 80 or 120 Present: let 0 ≤ r < 80 be a random number. If r < 40, BP is 40, else if r < 70, BP is 80, otherwise BP is 120.
21e33dc Variable Natural Gift: base power and type depend on held berry. See 2021030 and 20210E4 for corresponding tables.
21e398c 10 + 20 * factor Magnitude: let R = rand(100), factor = {0: R < 5, 1: 5 ≤ R < 15, 2: 15 ≤ R < 35, 3: 35 ≤ R < 65, 4: 65 ≤ R < 85, 5: 85 ≤ R < 95, 7: R ≥ 95}.
21e2720 30 * 2 ^ (use_counter + defense_curl) Rollout: use_counter counts successive and successful previous uses up to a maximum of 5, defense_curl is 1 if user used Defense Curl previously on field, 0 otherwise.
21e5d44 Variable Fling: base power depends on the held item. See 21D807C for table of items.
21e84b8 150 Grass/Fire/Water Pledge: if a slower ally used a different Pledge move this turn, it will skip its turn and this move's base power will be set to 150.

Modifiers for the base power

Trigger address Modifier Trigger description
21d9108 0x1800 If user has ability Technician and move's base power is ≤60.
21dc27c 0x1800 If user has ability Flare Boost, is burned and uses a special move.
21dc6c0 0x14CD If user has ability Analytic, move isn't Future Sight or Doom Desire and target has already moved this turn.
21d9174 0x1333 If user has ability Reckless and move has recoil or is either Jump Kick or Hi Jump Kick.
21d9138 0x1333 If the user has ability Iron Fist and move has the "Punching move" (0x7) flag set.
21dc238 0x1800 If user has ability Toxic Boost, is poisoned and move is physical.
21d9090 Variable If user has ability Rivalry. The value of the modifier is 0x1000 if either the user or target is genderless, 0x1400 if the user and target are of the same gender and 0xC00 otherwise.
21dc718 0x14CD If user has ability Sand Force and move is Rock, Ground or Steel type.
21da864 0x800 If target has ability Heatproof and move is Fire type.
21daa90 0x1400 If target has ability Dry Skin and move is Fire type.
21dbf48 0x14CD If the user has ability Sheer Force and move has a flag (0xA) set.
21d9dc4 Internal.
Multiple 0x1333 Type boosting items, plates, incenses. All are wrappers for the 21DF95C trigger. List of locations:
21df7a8, 21df878, 21df760, 21df748, 21df778, 21df7c0, 21df860, 21df890, 21df730, 21df908, 21df950, 21df790, 21df7d8, 21df7f0, 21df808, 21df718, 21df8c0, 21df938, 21df920, 21df8d8, 21df8a8.
21de6ec 0x1199 If user holds a Muscle Band and move is physical.
21df994 0x1333 If user is Palkia, holds the Lustrous Orb and move is Water or Dragon type.
21de72c 0x1199 If user holds Wise Glasses and move is special.
21df458 0x1333 If user is Giratina, holds the Griseous Orb and move is Dragon or Ghost type.
21df8f0 0x1333 If user holds Odd Incense and move is Psychic type.
21df9e8 0x1333 If user is Dialga, holds the Adamant Orb and move is Steel or Dragon type.
21e01e4 0x1800 If user holds a Normal Gem and move is normal type. Similar triggers for the other types are at:
21DFF14, 21DFF40, 21DFF6C, 21DFF98, 21DFFC4, 21DFFF0, 21E001C, 21E0048, 21E0074, 21E00A0, 21E00CC, 21E00F8, 21E0124, 21E0150, 21E017C, 21E01A8
21e2928 0x2000 If move is Facade and user is either paralyzed, poisoned or burned.
21e2a58 0x2000 If move is Brine and target's HP is ≤ 50%.
21e6fe8 0x2000 If move is Venoshock and target is poisoned.
21e729c 0x2000 If move is Retaliate and a Pokémon from the target's party fainted on the previous turn.
21e8330 0x2000 If move is either Fusion Bolt or Fusion Flare and the previously used move was respectively Fusion Flare or Fusion Bolt.
21e6f34 0x1800 If move was called using Me First.
21e64a0 0x800 If move is SolarBeam in non-sunny, non-default weather.
21e1f38 0x2000 If user used Charge the previous turn and move is Electric type.
21e5ff0 0x1800 If user has been the target of Helping Hand this turn.
6898158 0x548 If Water Sport was used by any Pokémon still on the field and move is Fire type.
6898110 0x548 If Mud Sport was used by any Pokémon still on the field and move is Electric type.

User attack stat

  1. MEMORY:021C7394 BaseAttackMods:                         @ CODE XREF: DamageCalc+9Ep
  2. MEMORY:021C7394 PUSH    {R3-R7,LR}
  3. MEMORY:021C7396 MOVS    R5, R3
  4. MEMORY:021C7398 MOVS    R7, R0
  5. MEMORY:021C739A LDRH    R0, [R5]
  6. MEMORY:021C739C MOVS    R6, R1
  7. MEMORY:021C739E STR     R2, [SP]
  8. MEMORY:021C73A0 BL      GetMoveCategory
  9. MEMORY:021C73A4 MOVS    R4, #0xA
  10. MEMORY:021C73A6 CMP     R0, #2
  11. MEMORY:021C73A8 BEQ     loc_21C73AC
  12. MEMORY:021C73AA MOVS    R4, #8
  13. MEMORY:021C73AC
  14. MEMORY:021C73AC loc_21C73AC:                            @ CODE XREF: BaseAttackMods+14j
  15. MEMORY:021C73AC LDR     R0, =0x30FE
  16. MEMORY:021C73AE BL      AllocateVolatileVariables
  17. MEMORY:021C73B2 MOVS    R0, R6
  18. MEMORY:021C73B4 BL      GetPkmId
  19. MEMORY:021C73B8 MOVS    R1, R0
  20. MEMORY:021C73BA MOVS    R0, #3
  21. MEMORY:021C73BC BL      StoreVolatileVariableFlag3e4
  22. MEMORY:021C73C0 LDR     R0, [SP]
  23. MEMORY:021C73C2 BL      GetPkmId
  24. MEMORY:021C73C6 MOVS    R1, R0
  25. MEMORY:021C73C8 MOVS    R0, #4
  26. MEMORY:021C73CA BL      StoreVolatileVariableFlag3e4
  27. MEMORY:021C73CE MOVS    R0, #0x3B @ ';'
  28. MEMORY:021C73D0 MOVS    R1, #0x1F
  29. MEMORY:021C73D2 BL      InitVolatileVariable
  30. MEMORY:021C73D6 MOVS    R0, #0x51 @ 'Q'
  31. MEMORY:021C73D8 MOVS    R1, #0
  32. MEMORY:021C73DA BL      InitVolatileVariable
  33. MEMORY:021C73DE MOVS    R0, R7
  34. MEMORY:021C73E0 MOVS    R1, #0x39 @ '9'
  35. MEMORY:021C73E2 BL      ApplyTriggers
  36. MEMORY:021C73E6 MOVS    R0, #0x3B @ ';'
  37. MEMORY:021C73E8 BL      ReadVolatileVariable
  38. MEMORY:021C73EC LSLS    R0, R0, #0x18
  39. MEMORY:021C73EE LSRS    R1, R0, #0x18
  40. MEMORY:021C73F0 CMP     R1, #0x1F
  41. MEMORY:021C73F2 BEQ     loc_21C73FC
  42. MEMORY:021C73F4 LDR     R0, [R7,#8]
  43. MEMORY:021C73F6 BL      GetPartyPkm
  44. MEMORY:021C73FA ADDS    R6, R0, #0
  45. MEMORY:021C73FC
  46. MEMORY:021C73FC loc_21C73FC:                            @ CODE XREF: BaseAttackMods+5Ej
  47. MEMORY:021C73FC MOVS    R0, #0x51 @ 'Q'
  48. MEMORY:021C73FE BL      ReadVolatileVariable
  49. MEMORY:021C7402 CMP     R0, #0
  50. MEMORY:021C7404 BEQ     loc_21C7410
  51. MEMORY:021C7406 MOVS    R0, R6
  52. MEMORY:021C7408 MOVS    R1, R4
  53. MEMORY:021C740A BL      RawBpkmStat
  54. MEMORY:021C740E B       loc_21C7428
  55. MEMORY:021C7410 @ ---------------------------------------------------------------------------
  56. MEMORY:021C7410
  57. MEMORY:021C7410 loc_21C7410:                            @ CODE XREF: BaseAttackMods+70j
  58. MEMORY:021C7410 LDR     R0, [SP,#0x18]
  59. MEMORY:021C7412 CMP     R0, #0
  60. MEMORY:021C7414 BEQ     loc_21C7420
  61. MEMORY:021C7416 MOVS    R0, R6
  62. MEMORY:021C7418 MOVS    R1, R4
  63. MEMORY:021C741A BL      CritAtkDefLevel
  64. MEMORY:021C741E B       loc_21C7428
  65. MEMORY:021C7420 @ ---------------------------------------------------------------------------
  66. MEMORY:021C7420
  67. MEMORY:021C7420 loc_21C7420:                            @ CODE XREF: BaseAttackMods+80j
  68. MEMORY:021C7420 MOVS    R0, R6
  69. MEMORY:021C7422 MOVS    R1, R4
  70. MEMORY:021C7424 BL      GetBpkmStat
  71. MEMORY:021C7428
  72. MEMORY:021C7428 loc_21C7428:                            @ CODE XREF: BaseAttackMods+7Aj
  73. MEMORY:021C7428                                         @ BaseAttackMods+8Aj
  74. MEMORY:021C7428 LSLS    R0, R0, #0x10
  75. MEMORY:021C742A LSRS    R4, R0, #0x10
  76. MEMORY:021C742C LDRH    R1, [R5]
  77. MEMORY:021C742E MOVS    R0, #0x12
  78. MEMORY:021C7430 BL      StoreVolatileVariableFlag3e4
  79. MEMORY:021C7434 LDRB    R1, [R5,#6]
  80. MEMORY:021C7436 MOVS    R0, #0x16
  81. MEMORY:021C7438 BL      StoreVolatileVariableFlag3e4
  82. MEMORY:021C743C LDR     R1, [R5,#8]
  83. MEMORY:021C743E MOVS    R0, #0x1A
  84. MEMORY:021C7440 BL      StoreVolatileVariableFlag3e4
  85. MEMORY:021C7444 MOVS    R0, #0x33 @ '3'
  86. MEMORY:021C7446 MOVS    R1, R4
  87. MEMORY:021C7448 BL      InitVolatileVariable
  88. MEMORY:021C744C MOVS    R1, 0x1000
  89. MEMORY:021C7450 LDR     R2, =0x19A
  90. MEMORY:021C7452 MOVS    R0, #0x35 @ '5'
  91. MEMORY:021C7454 LSLS    R3, R1, #5
  92. MEMORY:021C7456 BL      StoreVolatileVariableFlag3e3
  93. MEMORY:021C745A MOVS    R0, R7
  94. MEMORY:021C745C MOVS    R1, #0x3B @ ';'
  95. MEMORY:021C745E BL      ApplyTriggers
  96. MEMORY:021C7462 MOVS    R0, #0x33 @ '3'
  97. MEMORY:021C7464 BL      ReadVolatileVariable
  98. MEMORY:021C7468 LSLS    R0, R0, #0x10
  99. MEMORY:021C746A LSRS    R4, R0, #0x10
  100. MEMORY:021C746C MOVS    R0, #0x35 @ '5'
  101. MEMORY:021C746E BL      ReadVolatileVariable
  102. MEMORY:021C7472 MOVS    R1, R0
  103. MEMORY:021C7474 MOVS    R0, R4
  104. MEMORY:021C7476 BL      ApplyMod
  105. MEMORY:021C747A LSLS    R0, R0, #0x10
  106. MEMORY:021C747C LSRS    R4, R0, #0x10
  107. MEMORY:021C747E LDR     R0, =0x3123
  108. MEMORY:021C7480 BL      FreeVolatileVariable
  109. MEMORY:021C7484 MOVS    R0, R4
  110. MEMORY:021C7486 POP     {R3-R7,PC}
  111. MEMORY:021C7486 @ End of function BaseAttackMods

Base value

The first step of computing the attack stat is to decide whether the attack or special attack stat should be used, and on which Pokémon. By default, the user's attack is used if the move is physical and the special attack otherwise but this behavior can be altered by the following triggers:

Trigger address Trigger description
21da828 Unaware: if target has ability Unaware do not apply any attack level boosts.
21d8db0 Internal.
21e7320 Foul Play: use the target's base attack stat instead of the user's.
21e39b0 Internal.

Boost level

Once the base stat is decided, the stat boost level is applied:
  1. If a trigger decided to skip stat boosts, use the base stat.
  2. If the hit was critical and the boost level is negative, use the base stat.
  3. Otherwise, apply the factor corresponding to the boost level according to the table below (multiply stat by the dividend first then use unrounded division on divisor).
Stat boost level Multiplier Decimal Approximate
-62/80.25
-52/70.2857
-42/60.3333
-32/50.4
-22/40.5
-12/30.6667
02/21
+13/21.5
+24/22
+35/22.5
+46/23
+57/23.5
+68/24

Attack modifiers

The final attack stat is altered using the following modifiers:
Trigger address Modifier Trigger description
21d871c 0x800 If target has ability Thick Fat and move is Ice or Fire type.
21d8c78 0x1800 If user has ability Torrent, has MaxHP ÷ 3 or less HP and move is water type.
21d8d14 0x1800 If user has ability Guts, has a status problem and move is physical.
21d8cb0 0x1800 If user has ability Swarm, has MaxHP ÷ 3 or less HP and move is bug type.
21d8c94 0x1800 If user has ability Overgrow, has MaxHP ÷ 3 or less HP and move is grass type.
21d8d60 0x1800 If user has ability Plus or Minus and an ally has ability Plus or Minus and move is special.
21d8c5c 0x1800 If user has ability Blaze, has MaxHP ÷ 3 or less HP and move is fire type.
21dc0dc 0x800 If user has ability Defeatist and CurrentHP ≤ MaxHP ÷ 2.
21d8754 0x2000 If user has ability Pure Power or Huge Power and move is physical.
21d9954 0x1800 If user has ability Solar Power and weather is intense sunlight and move is special.
21d8894 0x1800 If user has ability Hustle and move is physical. This is a special trigger in the sense that instead of chaining it will directly apply the 0x1800 on the current attack stat instead of being chained with others.
21daf04 0x1800 If user has ability Flash Fire activated and move is Fire type.
21d892c 0x800 If user has ability Slow Start, has been on field for less than 5 turns and move is physical.
21d8fec 0x1800 If ally is Cherrim and has ability Flower Gift, weather is intense sunlight and move is physical.
21db424 Internal.
21de91c 0x2000 If user is Cubone or Marowak, holds a Thick Club and move is physical.
21de76c 0x2000 If user is Clamperl, holds a DeepSeaTooth and move is special.
21df53c 0x2000 If user is Pikachu and holds a Light Ball.
21de898 0x1800 If user is Latios or Latias, holds a Soul Dew and move is special.
21de968 0x1800 If user is holding Choice Band and move is physical.
21de9a0 0x1800 If user is holding Choice Specs and move is special.
21e310c Internal.

Target defense stat

  1. MEMORY:021C7494 BaseDefenseMods:                        @ CODE XREF: DamageCalc+AEp
  2. MEMORY:021C7494 PUSH    {R4-R7,LR}
  3. MEMORY:021C7496 SUB     SP, SP, #0xC
  4. MEMORY:021C7498 MOVS    R6, R3
  5. MEMORY:021C749A STR     R0, [SP]
  6. MEMORY:021C749C LDRH    R0, [R6]
  7. MEMORY:021C749E STR     R1, [SP,#4]
  8. MEMORY:021C74A0 MOVS    R5, R2
  9. MEMORY:021C74A2 BL      GetMoveCategory
  10. MEMORY:021C74A6 MOVS    R4, #0xB
  11. MEMORY:021C74A8 CMP     R0, #2
  12. MEMORY:021C74AA BEQ     loc_21C74AE
  13. MEMORY:021C74AC MOVS    R4, #9
  14. MEMORY:021C74AE
  15. MEMORY:021C74AE loc_21C74AE:                            @ CODE XREF: BaseDefenseMods+16j
  16. MEMORY:021C74AE LDR     R0, [R6,#8]
  17. MEMORY:021C74B0 STR     R0, [SP,#8]
  18. MEMORY:021C74B2 LDR     R0, =0x3133
  19. MEMORY:021C74B4 BL      AllocateVolatileVariables
  20. MEMORY:021C74B8 LDR     R0, [SP,#4]
  21. MEMORY:021C74BA BL      GetPkmId
  22. MEMORY:021C74BE MOVS    R1, R0
  23. MEMORY:021C74C0 MOVS    R0, #3
  24. MEMORY:021C74C2 BL      StoreVolatileVariableFlag3e4
  25. MEMORY:021C74C6 MOVS    R0, R5
  26. MEMORY:021C74C8 BL      GetPkmId
  27. MEMORY:021C74CC MOVS    R1, R0
  28. MEMORY:021C74CE MOVS    R0, #4
  29. MEMORY:021C74D0 BL      StoreVolatileVariableFlag3e4
  30. MEMORY:021C74D4 MOVS    R0, #0x3C @ '<'
  31. MEMORY:021C74D6 MOVS    R1, R4
  32. MEMORY:021C74D8 BL      StoreVolatileVariableFlag3e4
  33. MEMORY:021C74DC MOVS    R0, #0x3D @ '='
  34. MEMORY:021C74DE MOVS    R1, #0
  35. MEMORY:021C74E0 BL      InitVolatileVariable
  36. MEMORY:021C74E4 MOVS    R0, #0x51 @ 'Q'
  37. MEMORY:021C74E6 MOVS    R1, #0
  38. MEMORY:021C74E8 BL      StoreVolatileVariableFlag3e1
  39. MEMORY:021C74EC LDR     R0, [SP]
  40. MEMORY:021C74EE MOVS    R1, #0x3A @ ':'
  41. MEMORY:021C74F0 BL      ApplyTriggers
  42. MEMORY:021C74F4 MOVS    R0, #0x3D @ '='
  43. MEMORY:021C74F6 BL      ReadVolatileVariable
  44. MEMORY:021C74FA MOVS    R1, #1
  45. MEMORY:021C74FC TST     R0, R1
  46. MEMORY:021C74FE BEQ     loc_21C7516
  47. MEMORY:021C7500 CMP     R4, #9
  48. MEMORY:021C7502 BNE     loc_21C7508
  49. MEMORY:021C7504 MOVS    R4, #0xB
  50. MEMORY:021C7506 B       loc_21C750A
  51. MEMORY:021C7508 @ ---------------------------------------------------------------------------
  52. MEMORY:021C7508
  53. MEMORY:021C7508 loc_21C7508:                            @ CODE XREF: BaseDefenseMods+6Ej
  54. MEMORY:021C7508 MOVS    R4, #9
  55. MEMORY:021C750A
  56. MEMORY:021C750A loc_21C750A:                            @ CODE XREF: BaseDefenseMods+72j
  57. MEMORY:021C750A CMP     R4, #9
  58. MEMORY:021C750C BNE     loc_21C7512
  59. MEMORY:021C750E MOVS    R0, #1
  60. MEMORY:021C7510 B       loc_21C7514
  61. MEMORY:021C7512 @ ---------------------------------------------------------------------------
  62. MEMORY:021C7512
  63. MEMORY:021C7512 loc_21C7512:                            @ CODE XREF: BaseDefenseMods+78j
  64. MEMORY:021C7512 MOVS    R0, #2
  65. MEMORY:021C7514
  66. MEMORY:021C7514 loc_21C7514:                            @ CODE XREF: BaseDefenseMods+7Cj
  67. MEMORY:021C7514 STR     R0, [SP,#8]
  68. MEMORY:021C7516
  69. MEMORY:021C7516 loc_21C7516:                            @ CODE XREF: BaseDefenseMods+6Aj
  70. MEMORY:021C7516 MOVS    R0, #0x51 @ 'Q'
  71. MEMORY:021C7518 BL      ReadVolatileVariable
  72. MEMORY:021C751C LSLS    R0, R0, #0x18
  73. MEMORY:021C751E LSRS    R7, R0, #0x18
  74. MEMORY:021C7520 LDR     R0, =0x3142
  75. MEMORY:021C7522 BL      FreeVolatileVariable
  76. MEMORY:021C7526 CMP     R7, #0
  77. MEMORY:021C7528 BEQ     loc_21C7534
  78. MEMORY:021C752A MOVS    R0, R5
  79. MEMORY:021C752C MOVS    R1, R4
  80. MEMORY:021C752E BL      RawBpkmStat
  81. MEMORY:021C7532 B       loc_21C754C
  82. MEMORY:021C7534 @ ---------------------------------------------------------------------------
  83. MEMORY:021C7534
  84. MEMORY:021C7534 loc_21C7534:                            @ CODE XREF: BaseDefenseMods+94j
  85. MEMORY:021C7534 LDR     R0, [SP,#0x20]
  86. MEMORY:021C7536 CMP     R0, #0
  87. MEMORY:021C7538 BEQ     loc_21C7544
  88. MEMORY:021C753A MOVS    R0, R5
  89. MEMORY:021C753C MOVS    R1, R4
  90. MEMORY:021C753E BL      CritAtkDefLevel
  91. MEMORY:021C7542 B       loc_21C754C
  92. MEMORY:021C7544 @ ---------------------------------------------------------------------------
  93. MEMORY:021C7544
  94. MEMORY:021C7544 loc_21C7544:                            @ CODE XREF: BaseDefenseMods+A4j
  95. MEMORY:021C7544 MOVS    R0, R5
  96. MEMORY:021C7546 MOVS    R1, R4
  97. MEMORY:021C7548 BL      GetBpkmStat
  98. MEMORY:021C754C
  99. MEMORY:021C754C loc_21C754C:                            @ CODE XREF: BaseDefenseMods+9Ej
  100. MEMORY:021C754C                                         @ BaseDefenseMods+AEj
  101. MEMORY:021C754C LSLS    R0, R0, #0x10
  102. MEMORY:021C754E LSRS    R7, R0, #0x10
  103. MEMORY:021C7550 LDR     R0, [SP]
  104. MEMORY:021C7552 BL      GetActiveWeather
  105. MEMORY:021C7556 CMP     R0, #4
  106. MEMORY:021C7558 BNE     loc_21C7578
  107. MEMORY:021C755A MOVS    R0, R5
  108. MEMORY:021C755C MOVS    R1, #5
  109. MEMORY:021C755E BL      IsMoveOfUserType
  110. MEMORY:021C7562 CMP     R0, #0
  111. MEMORY:021C7564 BEQ     loc_21C7578
  112. MEMORY:021C7566 CMP     R4, #0xB
  113. MEMORY:021C7568 BNE     loc_21C7578
  114. MEMORY:021C756A MOVS    R1, #6
  115. MEMORY:021C756C MOVS    R0, R7
  116. MEMORY:021C756E LSLS    R1, R1, #0xA
  117. MEMORY:021C7570 BL      ApplyMod
  118. MEMORY:021C7574 LSLS    R0, R0, #0x10
  119. MEMORY:021C7576 LSRS    R7, R0, #0x10
  120. MEMORY:021C7578
  121. MEMORY:021C7578 loc_21C7578:                            @ CODE XREF: BaseDefenseMods+C4j
  122. MEMORY:021C7578                                         @ BaseDefenseMods+D0j ...
  123. MEMORY:021C7578 LDR     R4, =0x3157
  124. MEMORY:021C757A MOVS    R0, R4
  125. MEMORY:021C757C BL      AllocateVolatileVariables
  126. MEMORY:021C7580 LDR     R0, [SP,#4]
  127. MEMORY:021C7582 BL      GetPkmId
  128. MEMORY:021C7586 MOVS    R1, R0
  129. MEMORY:021C7588 MOVS    R0, #3
  130. MEMORY:021C758A BL      StoreVolatileVariableFlag3e4
  131. MEMORY:021C758E MOVS    R0, R5
  132. MEMORY:021C7590 BL      GetPkmId
  133. MEMORY:021C7594 MOVS    R1, R0
  134. MEMORY:021C7596 MOVS    R0, #4
  135. MEMORY:021C7598 MOVS    R5, #4
  136. MEMORY:021C759A BL      StoreVolatileVariableFlag3e4
  137. MEMORY:021C759E LDRH    R1, [R6]
  138. MEMORY:021C75A0 MOVS    R0, #0x12
  139. MEMORY:021C75A2 BL      StoreVolatileVariableFlag3e4
  140. MEMORY:021C75A6 LDRB    R1, [R6,#6]
  141. MEMORY:021C75A8 MOVS    R0, #0x16
  142. MEMORY:021C75AA BL      StoreVolatileVariableFlag3e4
  143. MEMORY:021C75AE LDR     R1, [SP,#8]
  144. MEMORY:021C75B0 MOVS    R0, #0x1A
  145. MEMORY:021C75B2 BL      StoreVolatileVariableFlag3e4
  146. MEMORY:021C75B6 MOVS    R0, #0x34 @ '4'
  147. MEMORY:021C75B8 MOVS    R1, R7
  148. MEMORY:021C75BA BL      InitVolatileVariable
  149. MEMORY:021C75BE LDR     R2, =0x19A
  150. MEMORY:021C75C0 MOVS    R0, #0x35 @ '5'
  151. MEMORY:021C75C2 LSLS    R1, R5, #0xA
  152. MEMORY:021C75C4 LSLS    R3, R5, #0xF
  153. MEMORY:021C75C6 BL      StoreVolatileVariableFlag3e3
  154. MEMORY:021C75CA LDR     R0, [SP]
  155. MEMORY:021C75CC MOVS    R1, #0x3C @ '<'
  156. MEMORY:021C75CE BL      ApplyTriggers
  157. MEMORY:021C75D2 MOVS    R0, #0x34 @ '4'
  158. MEMORY:021C75D4 BL      ReadVolatileVariable
  159. MEMORY:021C75D8 LSLS    R0, R0, #0x10
  160. MEMORY:021C75DA LSRS    R5, R0, #0x10
  161. MEMORY:021C75DC MOVS    R0, #0x35 @ '5'
  162. MEMORY:021C75DE BL      ReadVolatileVariable
  163. MEMORY:021C75E2 ADDS    R4, #0xB
  164. MEMORY:021C75E4 MOVS    R6, R0
  165. MEMORY:021C75E6 MOVS    R0, R4
  166. MEMORY:021C75E8 BL      FreeVolatileVariable
  167. MEMORY:021C75EC MOVS    R0, R5
  168. MEMORY:021C75EE MOVS    R1, R6
  169. MEMORY:021C75F0 BL      ApplyMod
  170. MEMORY:021C75F4 LSLS    R0, R0, #0x10
  171. MEMORY:021C75F6 LSRS    R0, R0, #0x10
  172. MEMORY:021C75F8 ADD     SP, SP, #0xC
  173. MEMORY:021C75FA POP     {R4-R7,PC}
  174. MEMORY:021C75FA @ End of function BaseDefenseMods

Base value

Just like for the attack stat, the first step is to decide which defense stat to use and whether to apply the active boost level. This is done by the following triggers:

Trigger address Trigger description
21da840 Unaware: if foe has ability Unaware do not apply any Defense level boosts.
21d8db0 Internal.
21e7944 This triggers is used for special moves that deal physical damage. It replaces the identifier of the base special defense stat with the one for defense.
21e797c Chip Away: ignore defense level boosts if foe has it.
68981a0 Wonder Room: has the same effect as 21e7944 but for all Pokémon on field. Will also cancel the effect of 21e7944.

Boost level

This works like attack boosts except the base defense stat is used on critical hits if the boost level is positive.

Sandstorm modifier

At this point, if the current weather (after triggers) is Sandstorm, the user is Rock type and the base stat was special attack, apply a 0x1800 modifier to the current defense stat. This is done regardless of critical hits and before any other modifier.

Defense modifiers

The final defense stat is altered using the following modifiers:
Trigger address Modifier Trigger description
21d91bc 0x1800 If target has ability Marvel Scale, has a status problem and move is physical.
21d903c 0x1800 If ally is Cherrim and has ability Flower Gift, weather is intense sunlight and move is special.
21db8f0 Internal.
21de7bc 0x1800 Is target is Clamperl, holds a DeepSeaScale and move is special.
21de804 0x2000 Is target is (untransformed) Ditto, holds Metal Powder and move is physical.
21dfaa8 0x1800 If target is holding Eviolite and is not fully evolved.
21de8d4 0x1800 If target is Latios or Latias holding a Soul Dew and move is special.

Special cases

The following moves do not depend on the user's attack or the target's defense and are handled by specific triggers:
Trigger address Trigger description
21e1608 Psywave: damage is always max(1, ((rand(101) + 50) * UserLevel) ÷ 100)
21e15d0 Night Shade: damage is always UserLevel.
21e1504 SonicBoom: damage is always 20.
21e1498 Super Fang: damage is always max(1, TargetHP ÷ 2).
21e14e0 Dragon Rage: damage is always 40.
21e1578 Endeavor: damage is always max(0, TargetHP-UserHP).
21e7c98 Final Gambit: damage is always UserHP.
21e0838 Brick Break: cancels the effect of Reflect / Light Screen.
21e1978 Counter: if last Pokémon to hit the user was a foe using a physical move, use double the set damage.
21e19bc Mirror Coat: same as Counter for special moves.
21e1a00 Metal Burst: if the user was hit by an attack earlier this turn, use 1.5 times the set damage.
21e3e50 Bide: store energy for 2 turns, then set damage to twice the total damage dealt to user during the charging turns.