ref: 0cf4eb68955952659b0e94fbeae0a75fe36255ae
parent: a0cc4a33929f6aeb08a733c4a985c3bbb24ef55f
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Fri Jan 26 06:36:00 EST 2018
Move-unique effect commands consistently go in engine/battle/move_effects/
--- a/docs/bugs_and_glitches.md
+++ b/docs/bugs_and_glitches.md
@@ -155,7 +155,7 @@
([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y))
-This is a bug with `BattleCommand_BellyDrum` in [engine/battle/effect_commands.asm](/engine/battle/effect_commands.asm):
+This is a bug with `BattleCommand_BellyDrum` in [engine/battle/move_effects/belly_drum.asm](/engine/battle/move_effects/belly_drum.asm):
```asm
BattleCommand_BellyDrum: ; 37c1a
@@ -307,7 +307,7 @@
([Video](https://www.youtube.com/watch?v=202-iAsrIa8))
-This is a bug with `BattleCommand_BeatUp` in [engine/battle/effect_commands.asm](/engine/battle/effect_commands.asm):
+This is a bug with `BattleCommand_BeatUp` in [engine/battle/move_effects/beat_up.asm](/engine/battle/move_effects/beat_up.asm):
```asm
.got_mon
@@ -346,7 +346,7 @@
This bug existed for all battles in Gold and Silver, and was only fixed for single-player battles in Crystal to preserve link compatibility.
-This is a bug with `BattleCommand_Present` in [engine/battle/effect_commands/present.asm](/engine/battle/effect_commands/present.asm):
+This is a bug with `BattleCommand_Present` in [engine/battle/move_effects/present.asm](/engine/battle/move_effects/present.asm):
```asm
BattleCommand_Present: ; 37874
--- a/engine/battle/effect_commands.asm
+++ b/engine/battle/effect_commands.asm
@@ -1306,47 +1306,9 @@
; 346b2
-BattleCommand_TripleKick: ; 346b2
-; triplekick
+INCLUDE "engine/battle/move_effects/triple_kick.asm"
- ld a, [wKickCounter]
- ld b, a
- inc b
- ld hl, CurDamage + 1
- ld a, [hld]
- ld e, a
- ld a, [hli]
- ld d, a
-.next_kick
- dec b
- ret z
- ld a, [hl]
- add e
- ld [hld], a
- ld a, [hl]
- adc d
- ld [hli], a
-; No overflow.
- jr nc, .next_kick
- ld a, $ff
- ld [hld], a
- ld [hl], a
- ret
-
-; 346cd
-
-
-BattleCommand_KickCounter: ; 346cd
-; kickcounter
-
- ld hl, wKickCounter
- inc [hl]
- ret
-
-; 346d2
-
-
BattleCommand_Stab: ; 346d2
; STAB = Same Type Attack Bonus
ld a, BATTLE_VARS_MOVE_ANIM
@@ -1637,10 +1599,12 @@
; 3484e
+
INCLUDE "engine/battle/ai/switch.asm"
INCLUDE "data/types/type_matchups.asm"
+
BattleCommand_DamageVariation: ; 34cfd
; damagevariation
@@ -2144,13 +2108,13 @@
ld a, BATTLE_VARS_MOVE_EFFECT
call GetBattleVar
cp EFFECT_MULTI_HIT
- jr z, .multihit
+ jr z, .alternate_anim
cp EFFECT_CONVERSION
- jr z, .conversion
+ jr z, .alternate_anim
cp EFFECT_DOUBLE_HIT
- jr z, .doublehit
+ jr z, .alternate_anim
cp EFFECT_POISON_MULTI_HIT
- jr z, .twineedle
+ jr z, .alternate_anim
cp EFFECT_TRIPLE_KICK
jr z, .triplekick
xor a
@@ -2157,7 +2121,6 @@
ld [wKickCounter], a
.triplekick
-
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVar
ld e, a
@@ -2167,18 +2130,13 @@
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVar
cp FLY
- jr z, .fly_dig
+ jr z, .clear_sprite
cp DIG
ret nz
-
-.fly_dig
-; clear sprite
+.clear_sprite
jp AppearUserLowerSub
-.multihit
-.conversion
-.doublehit
-.twineedle
+.alternate_anim
ld a, [wKickCounter]
and 1
xor 1
@@ -3136,227 +3094,9 @@
; 35461
-BattleCommand_BeatUp: ; 35461
-; beatup
+INCLUDE "engine/battle/move_effects/beat_up.asm"
- call ResetDamage
- ld a, [hBattleTurn]
- and a
- jp nz, .enemy_beats_up
- ld a, [PlayerSubStatus3]
- bit SUBSTATUS_IN_LOOP, a
- jr nz, .next_mon
- ld c, 20
- call DelayFrames
- xor a
- ld [PlayerRolloutCount], a
- ld [wd002], a
- ld [wBeatUpHitAtLeastOnce], a
- jr .got_mon
-.next_mon
- ld a, [PlayerRolloutCount]
- ld b, a
- ld a, [PartyCount]
- sub b
- ld [wd002], a
-
-.got_mon
- ld a, [wd002]
- ld hl, PartyMonNicknames
- call GetNick
- ld a, MON_HP
- call GetBeatupMonLocation
- ld a, [hli]
- or [hl]
- jp z, .beatup_fail ; fainted
- ld a, [wd002]
- ld c, a
- ld a, [CurBattleMon]
- ; BUG: this can desynchronize link battles
- ; Change "cp [hl]" to "cp c" to fix
- cp [hl]
- ld hl, BattleMonStatus
- jr z, .active_mon
- ld a, MON_STATUS
- call GetBeatupMonLocation
-.active_mon
- ld a, [hl]
- and a
- jp nz, .beatup_fail
-
- ld a, $1
- ld [wBeatUpHitAtLeastOnce], a
- ld hl, BeatUpAttackText
- call StdBattleTextBox
- ld a, [EnemyMonSpecies]
- ld [CurSpecies], a
- call GetBaseData
- ld a, [BaseDefense]
- ld c, a
- push bc
- ld a, MON_SPECIES
- call GetBeatupMonLocation
- ld a, [hl]
- ld [CurSpecies], a
- call GetBaseData
- ld a, [BaseAttack]
- pop bc
- ld b, a
- push bc
- ld a, MON_LEVEL
- call GetBeatupMonLocation
- ld a, [hl]
- ld e, a
- pop bc
- ld a, [wPlayerMoveStructPower]
- ld d, a
- ret
-
-.enemy_beats_up
- ld a, [EnemySubStatus3]
- bit SUBSTATUS_IN_LOOP, a
- jr nz, .not_first_enemy_beatup
-
- xor a
- ld [EnemyRolloutCount], a
- ld [wd002], a
- ld [wBeatUpHitAtLeastOnce], a
- jr .enemy_continue
-
-.not_first_enemy_beatup
- ld a, [EnemyRolloutCount]
- ld b, a
- ld a, [OTPartyCount]
- sub b
- ld [wd002], a
-.enemy_continue
- ld a, [wBattleMode]
- dec a
- jr z, .wild
-
- ld a, [wLinkMode]
- and a
- jr nz, .link_or_tower
-
- ld a, [InBattleTowerBattle]
- and a
- jr nz, .link_or_tower
-
- ld a, [wd002]
- ld c, a
- ld b, 0
- ld hl, OTPartySpecies
- add hl, bc
- ld a, [hl]
- ld [wNamedObjectIndexBuffer], a
- call GetPokemonName
- jr .got_enemy_nick
-
-.link_or_tower
- ld a, [wd002]
- ld hl, OTPartyMonNicknames
- ld bc, NAME_LENGTH
- call AddNTimes
- ld de, StringBuffer1
- call CopyBytes
-.got_enemy_nick
- ld a, MON_HP
- call GetBeatupMonLocation
- ld a, [hli]
- or [hl]
- jp z, .beatup_fail
- ld a, [wd002]
- ld b, a
- ld a, [CurOTMon]
- cp b
- ld hl, EnemyMonStatus
- jr z, .active_enemy
-
- ld a, MON_STATUS
- call GetBeatupMonLocation
-.active_enemy
- ld a, [hl]
- and a
- jr nz, .beatup_fail
-
- ld a, $1
- ld [wBeatUpHitAtLeastOnce], a
- jr .finish_beatup
-
-.wild
- ld a, [EnemyMonSpecies]
- ld [wNamedObjectIndexBuffer], a
- call GetPokemonName
- ld hl, BeatUpAttackText
- call StdBattleTextBox
- jp EnemyAttackDamage
-
-.finish_beatup
- ld hl, BeatUpAttackText
- call StdBattleTextBox
- ld a, [BattleMonSpecies]
- ld [CurSpecies], a
- call GetBaseData
- ld a, [BaseDefense]
- ld c, a
- push bc
- ld a, MON_SPECIES
- call GetBeatupMonLocation
- ld a, [hl]
- ld [CurSpecies], a
- call GetBaseData
- ld a, [BaseAttack]
- pop bc
- ld b, a
- push bc
- ld a, MON_LEVEL
- call GetBeatupMonLocation
- ld a, [hl]
- ld e, a
- pop bc
- ld a, [wEnemyMoveStructPower]
- ld d, a
- ret
-
-; 355b0
-
-
-.beatup_fail ; 355b0
- ld b, buildopponentrage_command
- jp SkipToBattleCommand
-
-; 355b5
-
-
-BattleCommanda8: ; 355b5
- ld a, [wBeatUpHitAtLeastOnce]
- and a
- ret nz
-
- jp PrintButItFailed
-
-; 355bd
-
-
-GetBeatupMonLocation: ; 355bd
- push bc
- ld c, a
- ld b, 0
- ld a, [hBattleTurn]
- and a
- ld hl, PartyMon1Species
- jr z, .got_species
- ld hl, OTPartyMon1Species
-
-.got_species
- ld a, [wd002]
- add hl, bc
- call GetPartyLocation
- pop bc
- ret
-
-
BattleCommand_ClearMissDamage: ; 355d5
; clearmissdamage
ld a, [AttackMissed]
@@ -3691,7 +3431,7 @@
cp b
jr nc, .psywave_loop
ld b, a
- ld a, $0
+ ld a, 0
jr .got_power
.super_fang
@@ -3712,9 +3452,9 @@
and a
jr nz, .got_power
or b
- ld a, $0
+ ld a, 0
jr nz, .got_power
- ld b, $1
+ ld b, 1
jr .got_power
.got_power
@@ -3806,520 +3546,21 @@
INCLUDE "data/moves/flail_reversal_power.asm"
-BattleCommand_Counter: ; 35813
-; counter
+INCLUDE "engine/battle/move_effects/counter.asm"
- ld a, 1
- ld [AttackMissed], a
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- ret z
+INCLUDE "engine/battle/move_effects/encore.asm"
- ld b, a
- callfar GetMoveEffect
- ld a, b
- cp EFFECT_COUNTER
- ret z
+INCLUDE "engine/battle/move_effects/pain_split.asm"
- call BattleCommand_ResetTypeMatchup
- ld a, [wTypeMatchup]
- and a
- ret z
+INCLUDE "engine/battle/move_effects/snore.asm"
- call CheckOpponentWentFirst
- ret z
+INCLUDE "engine/battle/move_effects/conversion2.asm"
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- dec a
- ld de, StringBuffer1
- call GetMoveData
+INCLUDE "engine/battle/move_effects/lock_on.asm"
- ld a, [StringBuffer1 + MOVE_POWER]
- and a
- ret z
+INCLUDE "engine/battle/move_effects/sketch.asm"
- ld a, [StringBuffer1 + MOVE_TYPE]
- cp SPECIAL
- ret nc
- ld hl, CurDamage
- ld a, [hli]
- or [hl]
- ret z
-
- ld a, [hl]
- add a
- ld [hld], a
- ld a, [hl]
- adc a
- ld [hl], a
- jr nc, .capped
- ld a, $ff
- ld [hli], a
- ld [hl], a
-.capped
-
- xor a
- ld [AttackMissed], a
- ret
-
-; 35864
-
-
-BattleCommand_Encore: ; 35864
-; encore
-
- ld hl, EnemyMonMoves
- ld de, EnemyEncoreCount
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld hl, BattleMonMoves
- ld de, PlayerEncoreCount
-.ok
- ld a, BATTLE_VARS_LAST_MOVE_OPP
- call GetBattleVar
- and a
- jp z, .failed
- cp STRUGGLE
- jp z, .failed
- cp ENCORE
- jp z, .failed
- cp MIRROR_MOVE
- jp z, .failed
- ld b, a
-
-.got_move
- ld a, [hli]
- cp b
- jr nz, .got_move
-
- ld bc, BattleMonPP - BattleMonMoves - 1
- add hl, bc
- ld a, [hl]
- and PP_MASK
- jp z, .failed
- ld a, [AttackMissed]
- and a
- jp nz, .failed
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_ENCORED, [hl]
- jp nz, .failed
- set SUBSTATUS_ENCORED, [hl]
- call BattleRandom
- and $3
- inc a
- inc a
- inc a
- ld [de], a
- call CheckOpponentWentFirst
- jr nz, .finish_move
- ld a, [hBattleTurn]
- and a
- jr z, .force_last_enemy_move
-
- push hl
- ld a, [LastPlayerMove]
- ld b, a
- ld c, 0
- ld hl, BattleMonMoves
-.find_player_move
- ld a, [hli]
- cp b
- jr z, .got_player_move
- inc c
- ld a, c
- cp NUM_MOVES
- jr c, .find_player_move
- pop hl
- res SUBSTATUS_ENCORED, [hl]
- xor a
- ld [de], a
- jr .failed
-
-.got_player_move
- pop hl
- ld a, c
- ld [CurMoveNum], a
- ld a, b
- ld [CurPlayerMove], a
- dec a
- ld de, wPlayerMoveStruct
- call GetMoveData
- jr .finish_move
-
-.force_last_enemy_move
- push hl
- ld a, [LastEnemyMove]
- ld b, a
- ld c, 0
- ld hl, EnemyMonMoves
-.find_enemy_move
- ld a, [hli]
- cp b
- jr z, .got_enemy_move
- inc c
- ld a, c
- cp NUM_MOVES
- jr c, .find_enemy_move
- pop hl
- res SUBSTATUS_ENCORED, [hl]
- xor a
- ld [de], a
- jr .failed
-
-.got_enemy_move
- pop hl
- ld a, c
- ld [CurEnemyMoveNum], a
- ld a, b
- ld [CurEnemyMove], a
- dec a
- ld de, wEnemyMoveStruct
- call GetMoveData
-
-.finish_move
- call AnimateCurrentMove
- ld hl, GotAnEncoreText
- jp StdBattleTextBox
-
-.failed
- jp PrintDidntAffect2
-
-; 35926
-
-
-BattleCommand_PainSplit: ; 35926
-; painsplit
-
- ld a, [AttackMissed]
- and a
- jp nz, .ButItFailed
- call CheckSubstituteOpp
- jp nz, .ButItFailed
- call AnimateCurrentMove
- ld hl, BattleMonMaxHP + 1
- ld de, EnemyMonMaxHP + 1
- call .PlayerShareHP
- ld a, $1
- ld [wWhichHPBar], a
- hlcoord 10, 9
- predef AnimateHPBar
- ld hl, EnemyMonHP
- ld a, [hli]
- ld [Buffer4], a
- ld a, [hli]
- ld [Buffer3], a
- ld a, [hli]
- ld [Buffer2], a
- ld a, [hl]
- ld [Buffer1], a
- call .EnemyShareHP
- xor a
- ld [wWhichHPBar], a
- call ResetDamage
- hlcoord 2, 2
- predef AnimateHPBar
- farcall _UpdateBattleHUDs
-
- ld hl, SharedPainText
- jp StdBattleTextBox
-
-.PlayerShareHP:
- ld a, [hld]
- ld [Buffer1], a
- ld a, [hld]
- ld [Buffer2], a
- ld a, [hld]
- ld b, a
- ld [Buffer3], a
- ld a, [hl]
- ld [Buffer4], a
- dec de
- dec de
- ld a, [de]
- dec de
- add b
- ld [CurDamage + 1], a
- ld b, [hl]
- ld a, [de]
- adc b
- srl a
- ld [CurDamage], a
- ld a, [CurDamage + 1]
- rr a
- ld [CurDamage + 1], a
- inc hl
- inc hl
- inc hl
- inc de
- inc de
- inc de
-
-.EnemyShareHP: ; 359ac
- ld c, [hl]
- dec hl
- ld a, [CurDamage + 1]
- sub c
- ld b, [hl]
- dec hl
- ld a, [CurDamage]
- sbc b
- jr nc, .skip
-
- ld a, [CurDamage]
- ld b, a
- ld a, [CurDamage + 1]
- ld c, a
-.skip
- ld a, c
- ld [hld], a
- ld [Buffer5], a
- ld a, b
- ld [hli], a
- ld [Buffer6], a
- ret
-
-; 359cd
-
-.ButItFailed:
- jp PrintDidntAffect2
-
-; 359d0
-
-
-BattleCommand_Snore: ; 359d0
-; snore
- ld a, BATTLE_VARS_STATUS
- call GetBattleVar
- and SLP
- ret nz
- call ResetDamage
- ld a, $1
- ld [AttackMissed], a
- call FailSnore
- jp EndMoveEffect
-
-; 359e6
-
-
-BattleCommand_Conversion2: ; 359e6
-; conversion2
-
- ld a, [AttackMissed]
- and a
- jr nz, .failed
- ld hl, BattleMonType1
- ld a, [hBattleTurn]
- and a
- jr z, .got_type
- ld hl, EnemyMonType1
-.got_type
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- jr z, .failed
- push hl
- dec a
- ld hl, Moves + MOVE_TYPE
- call GetMoveAttr
- ld d, a
- pop hl
- cp CURSE_T
- jr z, .failed
- call AnimateCurrentMove
- call BattleCommand_SwitchTurn
-
-.loop
- call BattleRandom
- and $1f
- cp UNUSED_TYPES
- jr c, .okay
- cp UNUSED_TYPES_END
- jr c, .loop
- cp TYPES_END
- jr nc, .loop
-.okay
- ld [hli], a
- ld [hld], a
- push hl
- ld a, BATTLE_VARS_MOVE_TYPE
- call GetBattleVarAddr
- push af
- push hl
- ld a, d
- ld [hl], a
- call BattleCheckTypeMatchup
- pop hl
- pop af
- ld [hl], a
- pop hl
- ld a, [wTypeMatchup]
- cp 10
- jr nc, .loop
- call BattleCommand_SwitchTurn
-
- ld a, [hl]
- ld [wNamedObjectIndexBuffer], a
- predef GetTypeName
- ld hl, TransformedTypeText
- jp StdBattleTextBox
-
-.failed
- jp FailConversion2
-
-; 35a53
-
-
-BattleCommand_LockOn: ; 35a53
-; lockon
-
- call CheckSubstituteOpp
- jr nz, .fail
-
- ld a, [AttackMissed]
- and a
- jr nz, .fail
-
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVarAddr
- set SUBSTATUS_LOCK_ON, [hl]
- call AnimateCurrentMove
-
- ld hl, TookAimText
- jp StdBattleTextBox
-
-.fail
- call AnimateFailedMove
- jp PrintDidntAffect
-
-; 35a74
-
-
-BattleCommand_Sketch: ; 35a74
-; sketch
-
- call ClearLastMove
-; Don't sketch during a link battle
- ld a, [wLinkMode]
- and a
- jr z, .not_linked
- call AnimateFailedMove
- jp PrintNothingHappened
-
-.not_linked
-; If the opponent has a substitute up, fail.
- call CheckSubstituteOpp
- jp nz, .fail
-; If the opponent is transformed, fail.
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_TRANSFORMED, [hl]
- jp nz, .fail
-; Get the user's moveset in its party struct.
-; This move replacement shall be permanent.
-; Pointer will be in de.
- ld a, MON_MOVES
- call UserPartyAttr
- ld d, h
- ld e, l
-; Get the battle move structs.
- ld hl, BattleMonMoves
- ld a, [hBattleTurn]
- and a
- jr z, .get_last_move
- ld hl, EnemyMonMoves
-.get_last_move
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- ld [wTypeMatchup], a
- ld b, a
-; Fail if move is invalid or is Struggle.
- and a
- jr z, .fail
- cp STRUGGLE
- jr z, .fail
-; Fail if user already knows that move
- ld c, NUM_MOVES
-.does_user_already_know_move
- ld a, [hli]
- cp b
- jr z, .fail
- dec c
- jr nz, .does_user_already_know_move
-; Find Sketch in the user's moveset.
-; Pointer in hl, and index in c.
- dec hl
- ld c, NUM_MOVES
-.find_sketch
- dec c
- ld a, [hld]
- cp SKETCH
- jr nz, .find_sketch
- inc hl
-; The Sketched move is loaded to that slot.
- ld a, b
- ld [hl], a
-; Copy the base PP from that move.
- push bc
- push hl
- dec a
- ld hl, Moves + MOVE_PP
- call GetMoveAttr
- pop hl
- ld bc, BattleMonPP - BattleMonMoves
- add hl, bc
- ld [hl], a
- pop bc
-
- ld a, [hBattleTurn]
- and a
- jr z, .user_trainer
- ld a, [wBattleMode]
- dec a
- jr nz, .user_trainer
-; wildmon
- ld a, [hl]
- push bc
- ld hl, wWildMonPP
- ld b, 0
- add hl, bc
- ld [hl], a
- ld hl, wWildMonMoves
- add hl, bc
- pop bc
- ld [hl], b
- jr .done_copy
-
-.user_trainer
- ld a, [hl]
- push af
- ld l, c
- ld h, 0
- add hl, de
- ld a, b
- ld [hl], a
- pop af
- ld de, MON_PP - MON_MOVES
- add hl, de
- ld [hl], a
-.done_copy
- call GetMoveName
- call AnimateCurrentMove
-
- ld hl, SketchedText
- jp StdBattleTextBox
-
-.fail
- call AnimateFailedMove
- jp PrintDidntAffect
-
-; 35b16
-
-
BattleCommand_DefrostOpponent: ; 35b16
; defrostopponent
; Thaw the opponent if frozen, and
@@ -4349,340 +3590,17 @@
; 35b33
-BattleCommand_SleepTalk: ; 35b33
-; sleeptalk
+INCLUDE "engine/battle/move_effects/sleep_talk.asm"
- call ClearLastMove
- ld a, [AttackMissed]
- and a
- jr nz, .fail
- ld a, [hBattleTurn]
- and a
- ld hl, BattleMonMoves + 1
- ld a, [DisabledMove]
- ld d, a
- jr z, .got_moves
- ld hl, EnemyMonMoves + 1
- ld a, [EnemyDisabledMove]
- ld d, a
-.got_moves
- ld a, BATTLE_VARS_STATUS
- call GetBattleVar
- and SLP
- jr z, .fail
- ld a, [hl]
- and a
- jr z, .fail
- call .safely_check_has_usable_move
- jr c, .fail
- dec hl
-.sample_move
- push hl
- call BattleRandom
- maskbits NUM_MOVES
- ld c, a
- ld b, 0
- add hl, bc
- ld a, [hl]
- pop hl
- and a
- jr z, .sample_move
- ld e, a
- ld a, BATTLE_VARS_MOVE_ANIM
- call GetBattleVar
- cp e
- jr z, .sample_move
- ld a, e
- cp d
- jr z, .sample_move
- call .check_two_turn_move
- jr z, .sample_move
- ld a, BATTLE_VARS_MOVE
- call GetBattleVarAddr
- ld a, e
- ld [hl], a
- call CheckUserIsCharging
- jr nz, .charging
- ld a, [wKickCounter]
- push af
- call BattleCommand_LowerSub
- pop af
- ld [wKickCounter], a
-.charging
- call LoadMoveAnim
- call UpdateMoveData
- jp ResetTurn
+INCLUDE "engine/battle/move_effects/destiny_bond.asm"
-.fail
- call AnimateFailedMove
- jp TryPrintButItFailed
+INCLUDE "engine/battle/move_effects/spite.asm"
-.safely_check_has_usable_move
- push hl
- push de
- push bc
- call .check_has_usable_move
- pop bc
- pop de
- pop hl
- ret
+INCLUDE "engine/battle/move_effects/false_swipe.asm"
-.check_has_usable_move
- ld a, [hBattleTurn]
- and a
- ld a, [DisabledMove]
- jr z, .got_move_2
+INCLUDE "engine/battle/move_effects/heal_bell.asm"
- ld a, [EnemyDisabledMove]
-.got_move_2
- ld b, a
- ld a, BATTLE_VARS_MOVE
- call GetBattleVar
- ld c, a
- dec hl
- ld d, NUM_MOVES
-.loop2
- ld a, [hl]
- and a
- jr z, .carry
- cp c
- jr z, .nope
- cp b
- jr z, .nope
-
- call .check_two_turn_move
- jr nz, .no_carry
-
-.nope
- inc hl
- dec d
- jr nz, .loop2
-
-.carry
- scf
- ret
-
-.no_carry
- and a
- ret
-
-.check_two_turn_move
- push hl
- push de
- push bc
-
- ld b, a
- callfar GetMoveEffect
- ld a, b
-
- pop bc
- pop de
- pop hl
-
- cp EFFECT_SKULL_BASH
- ret z
- cp EFFECT_RAZOR_WIND
- ret z
- cp EFFECT_SKY_ATTACK
- ret z
- cp EFFECT_SOLARBEAM
- ret z
- cp EFFECT_FLY
- ret z
- cp EFFECT_BIDE
- ret
-
-; 35bff
-
-
-BattleCommand_DestinyBond: ; 35bff
-; destinybond
-
- ld a, BATTLE_VARS_SUBSTATUS5
- call GetBattleVarAddr
- set SUBSTATUS_DESTINY_BOND, [hl]
- call AnimateCurrentMove
- ld hl, DestinyBondEffectText
- jp StdBattleTextBox
-
-; 35c0f
-
-
-BattleCommand_Spite: ; 35c0f
-; spite
-
- ld a, [AttackMissed]
- and a
- jp nz, .failed
- ld bc, PARTYMON_STRUCT_LENGTH ; ????
- ld hl, EnemyMonMoves
- ld a, [hBattleTurn]
- and a
- jr z, .got_moves
- ld hl, BattleMonMoves
-.got_moves
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- jr z, .failed
- cp STRUGGLE
- jr z, .failed
- ld b, a
- ld c, -1
-.loop
- inc c
- ld a, [hli]
- cp b
- jr nz, .loop
- ld [wTypeMatchup], a
- dec hl
- ld b, 0
- push bc
- ld c, BattleMonPP - BattleMonMoves
- add hl, bc
- pop bc
- ld a, [hl]
- and PP_MASK
- jr z, .failed
- push bc
- call GetMoveName
- ; lose 2-5 PP
- call BattleRandom
- and %11
- inc a
- inc a
- ld b, a
- ld a, [hl]
- and PP_MASK
- cp b
- jr nc, .deplete_pp
- ld b, a
-.deplete_pp
- ld a, [hl]
- sub b
- ld [hl], a
- push af
- ld a, MON_PP
- call OpponentPartyAttr
- ld d, b
- pop af
- pop bc
- add hl, bc
- ld e, a
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVar
- bit SUBSTATUS_TRANSFORMED, a
- jr nz, .transformed
- ld a, [hBattleTurn]
- and a
- jr nz, .not_wildmon
- ld a, [wBattleMode]
- dec a
- jr nz, .not_wildmon
- ld hl, wWildMonPP
- add hl, bc
-.not_wildmon
- ld [hl], e
-.transformed
- push de
- call AnimateCurrentMove
- pop de
- ld a, d
- ld [wTypeMatchup], a
- ld hl, SpiteEffectText
- jp StdBattleTextBox
-
-.failed
- jp PrintDidntAffect2
-
-; 35c94
-
-
-BattleCommand_FalseSwipe: ; 35c94
-; falseswipe
-
- ld hl, EnemyMonHP
- ld a, [hBattleTurn]
- and a
- jr z, .got_hp
- ld hl, BattleMonHP
-.got_hp
- ld de, CurDamage
- ld c, 2
- push hl
- push de
- call StringCmp
- pop de
- pop hl
- jr c, .done
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- dec a
- ld [de], a
- inc a
- jr nz, .okay
- dec de
- ld a, [de]
- dec a
- ld [de], a
-.okay
- ld a, [CriticalHit]
- cp 2
- jr nz, .carry
- xor a
- ld [CriticalHit], a
-.carry
- scf
- ret
-
-.done
- and a
- ret
-
-; 35cc9
-
-
-BattleCommand_HealBell: ; 35cc9
-; healbell
-
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- res SUBSTATUS_NIGHTMARE, [hl]
- ld de, PartyMon1Status
- ld a, [hBattleTurn]
- and a
- jr z, .got_status
- ld de, OTPartyMon1Status
-.got_status
- ld a, BATTLE_VARS_STATUS
- call GetBattleVarAddr
- xor a
- ld [hl], a
- ld h, d
- ld l, e
- ld bc, PARTYMON_STRUCT_LENGTH
- ld d, PARTY_LENGTH
-.loop
- ld [hl], a
- add hl, bc
- dec d
- jr nz, .loop
- call AnimateCurrentMove
-
- ld hl, BellChimedText
- call StdBattleTextBox
-
- ld a, [hBattleTurn]
- and a
- jp z, CalcPlayerStats
- jp CalcEnemyStats
-
-; 35d00
-
-
FarPlayBattleAnimation: ; 35d00
; play animation de
@@ -6377,113 +5295,9 @@
; 36671
-BattleCommand_StoreEnergy: ; 36671
-; storeenergy
+INCLUDE "engine/battle/move_effects/bide.asm"
- ld a, BATTLE_VARS_SUBSTATUS3
- call GetBattleVar
- bit SUBSTATUS_BIDE, a
- ret z
- ld hl, PlayerRolloutCount
- ld a, [hBattleTurn]
- and a
- jr z, .check_still_storing_energy
- ld hl, EnemyRolloutCount
-.check_still_storing_energy
- dec [hl]
- jr nz, .still_storing
-
- ld a, BATTLE_VARS_SUBSTATUS3
- call GetBattleVarAddr
- res SUBSTATUS_BIDE, [hl]
-
- ld hl, UnleashedEnergyText
- call StdBattleTextBox
-
- ld a, BATTLE_VARS_MOVE_POWER
- call GetBattleVarAddr
- ld a, 1
- ld [hl], a
- ld hl, PlayerDamageTaken + 1
- ld de, wPlayerCharging ; player
- ld a, [hBattleTurn]
- and a
- jr z, .player
- ld hl, EnemyDamageTaken + 1
- ld de, wEnemyCharging ; enemy
-.player
- ld a, [hld]
- add a
- ld b, a
- ld [CurDamage + 1], a
- ld a, [hl]
- rl a
- ld [CurDamage], a
- jr nc, .not_maxed
- ld a, $ff
- ld [CurDamage], a
- ld [CurDamage + 1], a
-.not_maxed
- or b
- jr nz, .built_up_something
- ld a, 1
- ld [AttackMissed], a
-.built_up_something
- xor a
- ld [hli], a
- ld [hl], a
- ld [de], a
-
- ld a, BATTLE_VARS_MOVE_ANIM
- call GetBattleVarAddr
- ld a, BIDE
- ld [hl], a
-
- ld b, unleashenergy_command
- jp SkipToBattleCommand
-
-.still_storing
- ld hl, StoringEnergyText
- call StdBattleTextBox
- jp EndMoveEffect
-
-; 366e5
-
-
-BattleCommand_UnleashEnergy: ; 366e5
-; unleashenergy
-
- ld de, PlayerDamageTaken
- ld bc, PlayerRolloutCount
- ld a, [hBattleTurn]
- and a
- jr z, .got_damage
- ld de, EnemyDamageTaken
- ld bc, EnemyRolloutCount
-.got_damage
- ld a, BATTLE_VARS_SUBSTATUS3
- call GetBattleVarAddr
- set SUBSTATUS_BIDE, [hl]
- xor a
- ld [de], a
- inc de
- ld [de], a
- ld [wPlayerMoveStructEffect], a
- ld [wEnemyMoveStructEffect], a
- call BattleRandom
- and 1
- inc a
- inc a
- ld [bc], a
- ld a, 1
- ld [wKickCounter], a
- call AnimateCurrentMove
- jp EndMoveEffect
-
-; 3671a
-
-
BattleCommand_CheckRampage: ; 3671a
; checkrampage
@@ -6554,99 +5368,9 @@
; 36778
-BattleCommand_Teleport: ; 36778
-; teleport
+INCLUDE "engine/battle/move_effects/teleport.asm"
- ld a, [BattleType]
- cp BATTLETYPE_SHINY
- jr z, .failed
- cp BATTLETYPE_TRAP
- jr z, .failed
- cp BATTLETYPE_CELEBI
- jr z, .failed
- cp BATTLETYPE_SUICUNE
- jr z, .failed
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVar
- bit SUBSTATUS_CANT_RUN, a
- jr nz, .failed
-; Only need to check these next things if it's your turn
- ld a, [hBattleTurn]
- and a
- jr nz, .enemy_turn
-; Can't teleport from a trainer battle
- ld a, [wBattleMode]
- dec a
- jr nz, .failed
-; If your level is greater than the opponent's, you run without fail.
- ld a, [CurPartyLevel]
- ld b, a
- ld a, [BattleMonLevel]
- cp b
- jr nc, .run_away
-; Generate a number between 0 and (YourLevel + TheirLevel).
- add b
- ld c, a
- inc c
-.loop_player
- call BattleRandom
- cp c
- jr nc, .loop_player
-; If that number is greater than 4 times your level, run away.
- srl b
- srl b
- cp b
- jr nc, .run_away
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-
-.enemy_turn
- ld a, [wBattleMode]
- dec a
- jr nz, .failed
- ld a, [BattleMonLevel]
- ld b, a
- ld a, [CurPartyLevel]
- cp b
- jr nc, .run_away
- add b
- ld c, a
- inc c
-.loop_enemy
- call BattleRandom
- cp c
- jr nc, .loop_enemy
- srl b
- srl b
- cp b
- ; This does the wrong thing. What was
- ; probably intended was jr c, .failed
- ; The way this is made makes enemy use
- ; of Teleport always succeed if able
- jr nc, .run_away
-.run_away
- call UpdateBattleMonInParty
- xor a
- ld [wNumHits], a
- inc a
- ld [wForcedSwitch], a
- ld [wKickCounter], a
- call SetBattleDraw
- call BattleCommand_LowerSub
- call LoadMoveAnim
- ld c, 20
- call DelayFrames
- call SetBattleDraw
-
- ld hl, FledFromBattleText
- jp StdBattleTextBox
-
-; 36804
-
-
SetBattleDraw: ; 36804
ld a, [wBattleResult]
and $c0
@@ -7420,44 +6144,11 @@
; 36c7e
-BattleCommand_Mist: ; 36c7e
-; mist
+INCLUDE "engine/battle/move_effects/mist.asm"
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- bit SUBSTATUS_MIST, [hl]
- jr nz, .already_mist
- set SUBSTATUS_MIST, [hl]
- call AnimateCurrentMove
- ld hl, MistText
- jp StdBattleTextBox
+INCLUDE "engine/battle/move_effects/focus_energy.asm"
-.already_mist
- call AnimateFailedMove
- jp PrintButItFailed
-; 36c98
-
-
-BattleCommand_FocusEnergy: ; 36c98
-; focusenergy
-
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- bit SUBSTATUS_FOCUS_ENERGY, [hl]
- jr nz, .already_pumped
- set SUBSTATUS_FOCUS_ENERGY, [hl]
- call AnimateCurrentMove
- ld hl, GettingPumpedText
- jp StdBattleTextBox
-
-.already_pumped
- call AnimateFailedMove
- jp PrintButItFailed
-
-; 36cb2
-
-
BattleCommand_Recoil: ; 36cb2
; recoil
@@ -7755,97 +6446,9 @@
; 36e7c
-BattleCommand_Substitute: ; 36e7c
-; substitute
+INCLUDE "engine/battle/move_effects/substitute.asm"
- call BattleCommand_MoveDelay
- ld hl, BattleMonMaxHP
- ld de, PlayerSubstituteHP
- ld a, [hBattleTurn]
- and a
- jr z, .got_hp
- ld hl, EnemyMonMaxHP
- ld de, EnemySubstituteHP
-.got_hp
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVar
- bit SUBSTATUS_SUBSTITUTE, a
- jr nz, .already_has_sub
-
- ld a, [hli]
- ld b, [hl]
- srl a
- rr b
- srl a
- rr b
- dec hl
- dec hl
- ld a, b
- ld [de], a
- ld a, [hld]
- sub b
- ld e, a
- ld a, [hl]
- sbc 0
- ld d, a
- jr c, .too_weak_to_sub
- ld a, d
- or e
- jr z, .too_weak_to_sub
- ld [hl], d
- inc hl
- ld [hl], e
-
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- set SUBSTATUS_SUBSTITUTE, [hl]
-
- ld hl, wPlayerWrapCount
- ld de, wPlayerTrappingMove
- ld a, [hBattleTurn]
- and a
- jr z, .player
- ld hl, wEnemyWrapCount
- ld de, wEnemyTrappingMove
-.player
-
- xor a
- ld [hl], a
- ld [de], a
- call _CheckBattleScene
- jr c, .no_anim
-
- xor a
- ld [wNumHits], a
- ld [FXAnimID + 1], a
- ld [wKickCounter], a
- ld a, SUBSTITUTE
- call LoadAnim
- jr .finish
-
-.no_anim
- call BattleCommand_RaiseSubNoAnim
-.finish
- ld hl, MadeSubstituteText
- call StdBattleTextBox
- jp RefreshBattleHuds
-
-.already_has_sub
- call CheckUserIsCharging
- call nz, BattleCommand_RaiseSub
- ld hl, HasSubstituteText
- jr .jp_stdbattletextbox
-
-.too_weak_to_sub
- call CheckUserIsCharging
- call nz, BattleCommand_RaiseSub
- ld hl, TooWeakSubText
-.jp_stdbattletextbox
- jp StdBattleTextBox
-
-; 36f0b
-
BattleCommand_RechargeNextTurn: ; 36f0b
; rechargenextturn
ld a, BATTLE_VARS_SUBSTATUS4
@@ -7867,16 +6470,9 @@
; 36f1d
-BattleCommand_Rage: ; 36f1d
-; rage
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- set SUBSTATUS_RAGE, [hl]
- ret
+INCLUDE "engine/battle/move_effects/rage.asm"
-; 36f25
-
BattleCommand_DoubleFlyingDamage: ; 36f25
; doubleflyingdamage
ld a, BATTLE_VARS_SUBSTATUS3_OPP
@@ -7915,318 +6511,19 @@
; 36f46
-BattleCommand_Mimic: ; 36f46
-; mimic
+INCLUDE "engine/battle/move_effects/mimic.asm"
- call ClearLastMove
- call BattleCommand_MoveDelay
- ld a, [AttackMissed]
- and a
- jr nz, .fail
- ld hl, BattleMonMoves
- ld a, [hBattleTurn]
- and a
- jr z, .player_turn
- ld hl, EnemyMonMoves
-.player_turn
- call CheckHiddenOpponent
- jr nz, .fail
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- jr z, .fail
- cp STRUGGLE
- jr z, .fail
- ld b, a
- ld c, NUM_MOVES
-.check_already_knows_move
- ld a, [hli]
- cp b
- jr z, .fail
- dec c
- jr nz, .check_already_knows_move
- dec hl
-.find_mimic
- ld a, [hld]
- cp MIMIC
- jr nz, .find_mimic
- inc hl
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- ld [hl], a
- ld [wNamedObjectIndexBuffer], a
- ld bc, BattleMonPP - BattleMonMoves
- add hl, bc
- ld [hl], 5
- call GetMoveName
- call AnimateCurrentMove
- ld hl, LearnedMoveText
- jp StdBattleTextBox
+INCLUDE "engine/battle/move_effects/leech_seed.asm"
-.fail
- jp FailMimic
+INCLUDE "engine/battle/move_effects/splash.asm"
-; 36f9d
+INCLUDE "engine/battle/move_effects/disable.asm"
+INCLUDE "engine/battle/move_effects/pay_day.asm"
-BattleCommand_LeechSeed: ; 36f9d
-; leechseed
- ld a, [AttackMissed]
- and a
- jr nz, .evaded
- call CheckSubstituteOpp
- jr nz, .evaded
+INCLUDE "engine/battle/move_effects/conversion.asm"
- ld de, EnemyMonType1
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld de, BattleMonType1
-.ok
- ld a, [de]
- cp GRASS
- jr z, .grass
- inc de
- ld a, [de]
- cp GRASS
- jr z, .grass
-
- ld a, BATTLE_VARS_SUBSTATUS4_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_LEECH_SEED, [hl]
- jr nz, .evaded
- set SUBSTATUS_LEECH_SEED, [hl]
- call AnimateCurrentMove
- ld hl, WasSeededText
- jp StdBattleTextBox
-
-.grass
- call AnimateFailedMove
- jp PrintDoesntAffect
-
-.evaded
- call AnimateFailedMove
- ld hl, EvadedText
- jp StdBattleTextBox
-
-; 36fe1
-
-
-BattleCommand_Splash: ; 36fe1
- call AnimateCurrentMove
- farcall StubbedTrainerRankings_Splash
- jp PrintNothingHappened
-
-; 36fed
-
-
-BattleCommand_Disable: ; 36fed
-; disable
-
- ld a, [AttackMissed]
- and a
- jr nz, .failed
-
- ld de, EnemyDisableCount
- ld hl, EnemyMonMoves
- ld a, [hBattleTurn]
- and a
- jr z, .got_moves
- ld de, PlayerDisableCount
- ld hl, BattleMonMoves
-.got_moves
-
- ld a, [de]
- and a
- jr nz, .failed
-
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- jr z, .failed
- cp STRUGGLE
- jr z, .failed
-
- ld b, a
- ld c, $ff
-.loop
- inc c
- ld a, [hli]
- cp b
- jr nz, .loop
-
- ld a, [hBattleTurn]
- and a
- ld hl, EnemyMonPP
- jr z, .got_pp
- ld hl, BattleMonPP
-.got_pp
- ld b, 0
- add hl, bc
- ld a, [hl]
- and a
- jr z, .failed
-.loop2
- call BattleRandom
- and 7
- jr z, .loop2
- inc a
- inc c
- swap c
- add c
- ld [de], a
- call AnimateCurrentMove
- ld hl, DisabledMove
- ld a, [hBattleTurn]
- and a
- jr nz, .got_disabled_move_pointer
- inc hl
-.got_disabled_move_pointer
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- ld [hl], a
- ld [wNamedObjectIndexBuffer], a
- call GetMoveName
- ld hl, WasDisabledText
- jp StdBattleTextBox
-
-.failed
- jp FailDisable
-
-; 3705c
-
-
-BattleCommand_PayDay: ; 3705c
-; payday
-
- xor a
- ld hl, StringBuffer1
- ld [hli], a
-
- ld a, [hBattleTurn]
- and a
- ld a, [BattleMonLevel]
- jr z, .ok
- ld a, [EnemyMonLevel]
-.ok
-
- add a
- ld hl, wPayDayMoney + 2
- add [hl]
- ld [hld], a
- jr nc, .done
- inc [hl]
- dec hl
- jr nz, .done
- inc [hl]
-.done
- ld hl, CoinsScatteredText
- jp StdBattleTextBox
-
-; 3707f
-
-
-BattleCommand_Conversion: ; 3707f
-; conversion
-
- ld hl, BattleMonMoves
- ld de, BattleMonType1
- ld a, [hBattleTurn]
- and a
- jr z, .got_moves
- ld hl, EnemyMonMoves
- ld de, EnemyMonType1
-.got_moves
- push de
- ld c, 0
- ld de, StringBuffer1
-.loop
- push hl
- ld b, 0
- add hl, bc
- ld a, [hl]
- pop hl
- and a
- jr z, .okay
- push hl
- push bc
- dec a
- ld hl, Moves + MOVE_TYPE
- call GetMoveAttr
- ld [de], a
- inc de
- pop bc
- pop hl
- inc c
- ld a, c
- cp NUM_MOVES
- jr c, .loop
-.okay
- ld a, $ff
- ld [de], a
- inc de
- ld [de], a
- inc de
- ld [de], a
- pop de
- ld hl, StringBuffer1
-.loop2
- ld a, [hl]
- cp -1
- jr z, .fail
- cp CURSE_T
- jr z, .next
- ld a, [de]
- cp [hl]
- jr z, .next
- inc de
- ld a, [de]
- dec de
- cp [hl]
- jr nz, .done
-.next
- inc hl
- jr .loop2
-
-.fail
- call AnimateFailedMove
- jp PrintButItFailed
-
-.done
-.loop3
- call BattleRandom
- maskbits NUM_MOVES
- ld c, a
- ld b, 0
- ld hl, StringBuffer1
- add hl, bc
- ld a, [hl]
- cp -1
- jr z, .loop3
- cp CURSE_T
- jr z, .loop3
- ld a, [de]
- cp [hl]
- jr z, .loop3
- inc de
- ld a, [de]
- dec de
- cp [hl]
- jr z, .loop3
- ld a, [hl]
- ld [de], a
- inc de
- ld [de], a
- ld [wNamedObjectIndexBuffer], a
- farcall GetTypeName
- call AnimateCurrentMove
- ld hl, TransformedTypeText
- jp StdBattleTextBox
-
-; 3710e
-
-
BattleCommand_ResetStats: ; 3710e
; resetstats
@@ -8347,8 +6644,10 @@
; 371cd
-INCLUDE "engine/battle/effect_commands/transform.asm"
+INCLUDE "engine/battle/move_effects/transform.asm"
+
+
BattleSideCopy: ; 372c6
; Copy bc bytes from hl to de if it's the player's turn.
; Copy bc bytes from de to hl if it's the enemy's turn.
@@ -8489,12 +6788,7 @@
; 37354
-FailSnore:
-FailDisable:
-FailConversion2:
-FailAttract:
-FailForesight:
-FailSpikes:
+FailMove:
call AnimateFailedMove
; fallthrough
; 37357
@@ -8541,44 +6835,13 @@
; 37380
-BattleCommand_Selfdestruct: ; 37380
- farcall StubbedTrainerRankings_Selfdestruct
- ld a, BATTLEANIM_PLAYER_DAMAGE
- ld [wNumHits], a
- ld c, 3
- call DelayFrames
- ld a, BATTLE_VARS_STATUS
- call GetBattleVarAddr
- xor a
- ld [hli], a
- inc hl
- ld [hli], a
- ld [hl], a
- ld a, $1
- ld [wKickCounter], a
- call BattleCommand_LowerSub
- call LoadMoveAnim
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- res SUBSTATUS_LEECH_SEED, [hl]
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVarAddr
- res SUBSTATUS_DESTINY_BOND, [hl]
- call _CheckBattleScene
- ret nc
- farcall DrawPlayerHUD
- farcall DrawEnemyHUD
- call WaitBGMap
- jp RefreshBattleHuds
+INCLUDE "engine/battle/move_effects/selfdestruct.asm"
-; 373c9
+INCLUDE "engine/battle/move_effects/mirror_move.asm"
+INCLUDE "engine/battle/move_effects/metronome.asm"
-INCLUDE "engine/battle/effect_commands/mirror_move.asm"
-INCLUDE "engine/battle/effect_commands/metronome.asm"
-
-
CheckUserMove: ; 37462
; Return z if the user has move a.
ld b, a
@@ -8623,7 +6886,7 @@
; 37492
-INCLUDE "engine/battle/effect_commands/thief.asm"
+INCLUDE "engine/battle/move_effects/thief.asm"
BattleCommand_ArenaTrap: ; 37517
@@ -8655,7 +6918,7 @@
; 37536
-INCLUDE "engine/battle/effect_commands/nightmare.asm"
+INCLUDE "engine/battle/move_effects/nightmare.asm"
BattleCommand_Defrost: ; 37563
@@ -8692,21 +6955,21 @@
; 37588
-INCLUDE "engine/battle/effect_commands/curse.asm"
+INCLUDE "engine/battle/move_effects/curse.asm"
-INCLUDE "engine/battle/effect_commands/protect.asm"
+INCLUDE "engine/battle/move_effects/protect.asm"
-INCLUDE "engine/battle/effect_commands/endure.asm"
+INCLUDE "engine/battle/move_effects/endure.asm"
-INCLUDE "engine/battle/effect_commands/spikes.asm"
+INCLUDE "engine/battle/move_effects/spikes.asm"
-INCLUDE "engine/battle/effect_commands/foresight.asm"
+INCLUDE "engine/battle/move_effects/foresight.asm"
-INCLUDE "engine/battle/effect_commands/perish_song.asm"
+INCLUDE "engine/battle/move_effects/perish_song.asm"
-INCLUDE "engine/battle/effect_commands/sandstorm.asm"
+INCLUDE "engine/battle/move_effects/sandstorm.asm"
-INCLUDE "engine/battle/effect_commands/rollout.asm"
+INCLUDE "engine/battle/move_effects/rollout.asm"
BattleCommand5d: ; 37791
@@ -8716,160 +6979,19 @@
; 37792
-BattleCommand_FuryCutter: ; 37792
-; furycutter
+INCLUDE "engine/battle/move_effects/fury_cutter.asm"
- ld hl, PlayerFuryCutterCount
- ld a, [hBattleTurn]
- and a
- jr z, .go
- ld hl, EnemyFuryCutterCount
+INCLUDE "engine/battle/move_effects/attract.asm"
-.go
- ld a, [AttackMissed]
- and a
- jp nz, ResetFuryCutterCount
+INCLUDE "engine/battle/move_effects/return.asm"
- inc [hl]
+INCLUDE "engine/battle/move_effects/present.asm"
-; Damage capped at 5 turns' worth (16x).
- ld a, [hl]
- ld b, a
- cp 6
- jr c, .checkdouble
- ld b, 5
+INCLUDE "engine/battle/move_effects/frustration.asm"
-.checkdouble
- dec b
- ret z
+INCLUDE "engine/battle/move_effects/safeguard.asm"
-; Double the damage
- ld hl, CurDamage + 1
- sla [hl]
- dec hl
- rl [hl]
- jr nc, .checkdouble
-; No overflow
- ld a, $ff
- ld [hli], a
- ld [hl], a
- ret
-
-; 377be
-
-
-ResetFuryCutterCount: ; 377be
-
- push hl
-
- ld hl, PlayerFuryCutterCount
- ld a, [hBattleTurn]
- and a
- jr z, .reset
- ld hl, EnemyFuryCutterCount
-
-.reset
- xor a
- ld [hl], a
-
- pop hl
- ret
-
-; 377ce
-
-
-INCLUDE "engine/battle/effect_commands/attract.asm"
-
-BattleCommand_HappinessPower: ; 3784b
-; happinesspower
- push bc
- ld hl, BattleMonHappiness
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld hl, EnemyMonHappiness
-.ok
- xor a
- ld [hMultiplicand + 0], a
- ld [hMultiplicand + 1], a
- ld a, [hl]
- ld [hMultiplicand + 2], a
- ld a, 10
- ld [hMultiplier], a
- call Multiply
- ld a, 25
- ld [hDivisor], a
- ld b, 4
- call Divide
- ld a, [hQuotient + 2]
- ld d, a
- pop bc
- ret
-
-; 37874
-
-
-INCLUDE "engine/battle/effect_commands/present.asm"
-
-BattleCommand_FrustrationPower: ; 3790e
-; frustrationpower
-
- push bc
- ld hl, BattleMonHappiness
- ld a, [hBattleTurn]
- and a
- jr z, .got_happiness
- ld hl, EnemyMonHappiness
-.got_happiness
- ld a, $ff
- sub [hl]
- ld [hMultiplicand + 2], a
- xor a
- ld [hMultiplicand + 0], a
- ld [hMultiplicand + 1], a
- ld a, 10
- ld [hMultiplier], a
- call Multiply
- ld a, 25
- ld [hDivisor], a
- ld b, 4
- call Divide
- ld a, [hQuotient + 2]
- ld d, a
- pop bc
- ret
-
-; 37939
-
-
-BattleCommand_Safeguard: ; 37939
-; safeguard
-
- ld hl, PlayerScreens
- ld de, PlayerSafeguardCount
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld hl, EnemyScreens
- ld de, EnemySafeguardCount
-.ok
- bit SCREENS_SAFEGUARD, [hl]
- jr nz, .failed
- set SCREENS_SAFEGUARD, [hl]
- ld a, 5
- ld [de], a
- call AnimateCurrentMove
- ld hl, CoveredByVeilText
- jp StdBattleTextBox
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-
-; 37962
-
-
SafeCheckSafeguard: ; 37962
push hl
ld hl, EnemyScreens
@@ -8906,348 +7028,15 @@
; 37991
-BattleCommand_GetMagnitude: ; 37991
-; getmagnitude
+INCLUDE "engine/battle/move_effects/magnitude.asm"
- push bc
- call BattleRandom
- ld b, a
- ld hl, MagnitudePower
-.loop
- ld a, [hli]
- cp b
- jr nc, .ok
- inc hl
- inc hl
- jr .loop
+INCLUDE "engine/battle/move_effects/baton_pass.asm"
-.ok
- ld d, [hl]
- push de
- inc hl
- ld a, [hl]
- ld [wTypeMatchup], a
- call BattleCommand_MoveDelay
- ld hl, MagnitudeText
- call StdBattleTextBox
- pop de
- pop bc
- ret
+INCLUDE "engine/battle/move_effects/pursuit.asm"
-INCLUDE "data/moves/magnitude_power.asm"
+INCLUDE "engine/battle/move_effects/rapid_spin.asm"
-BattleCommand_BatonPass: ; 379c9
-; batonpass
-
- ld a, [hBattleTurn]
- and a
- jp nz, .Enemy
-
-
-; Need something to switch to
- call CheckAnyOtherAlivePartyMons
- jp z, FailedBatonPass
-
- call UpdateBattleMonInParty
- call AnimateCurrentMove
-
- ld c, 50
- call DelayFrames
-
-; Transition into switchmon menu
- call LoadStandardMenuHeader
- farcall SetUpBattlePartyMenu_NoLoop
-
- farcall ForcePickSwitchMonInBattle
-
-; Return to battle scene
- call ClearPalettes
- farcall _LoadBattleFontsHPBar
- call CloseWindow
- call ClearSprites
- hlcoord 1, 0
- lb bc, 4, 10
- call ClearBox
- ld b, SCGB_BATTLE_COLORS
- call GetSGBLayout
- call SetPalettes
- call BatonPass_LinkPlayerSwitch
-
-; Mobile link battles handle entrances differently
- farcall CheckMobileBattleError
- jp c, EndMoveEffect
-
- ld hl, PassedBattleMonEntrance
- call CallBattleCore
-
- call ResetBatonPassStatus
- ret
-
-
-.Enemy:
-
-; Wildmons don't have anything to switch to
- ld a, [wBattleMode]
- dec a ; WILDMON
- jp z, FailedBatonPass
-
- call CheckAnyOtherAliveEnemyMons
- jp z, FailedBatonPass
-
- call UpdateEnemyMonInParty
- call AnimateCurrentMove
- call BatonPass_LinkEnemySwitch
-
-; Mobile link battles handle entrances differently
- farcall CheckMobileBattleError
- jp c, EndMoveEffect
-
-; Passed enemy PartyMon entrance
- xor a
- ld [wEnemySwitchMonIndex], a
- ld hl, EnemySwitch_SetMode
- call CallBattleCore
- ld hl, ResetBattleParticipants
- call CallBattleCore
- ld a, 1
- ld [wTypeMatchup], a
- ld hl, ApplyStatLevelMultiplierOnAllStats
- call CallBattleCore
-
- ld hl, SpikesDamage
- call CallBattleCore
-
- jr ResetBatonPassStatus
-
-; 37a67
-
-
-BatonPass_LinkPlayerSwitch: ; 37a67
- ld a, [wLinkMode]
- and a
- ret z
-
- ld a, 1
- ld [wPlayerAction], a
-
- call LoadStandardMenuHeader
- ld hl, LinkBattleSendReceiveAction
- call CallBattleCore
- call CloseWindow
-
- xor a
- ld [wPlayerAction], a
- ret
-
-; 37a82
-
-
-BatonPass_LinkEnemySwitch: ; 37a82
- ld a, [wLinkMode]
- and a
- ret z
-
- call LoadStandardMenuHeader
- ld hl, LinkBattleSendReceiveAction
- call CallBattleCore
-
- ld a, [OTPartyCount]
- add BATTLEACTION_SWITCH1
- ld b, a
- ld a, [wBattleAction]
- cp BATTLEACTION_SWITCH1
- jr c, .baton_pass
- cp b
- jr c, .switch
-
-.baton_pass
- ld a, [CurOTMon]
- add BATTLEACTION_SWITCH1
- ld [wBattleAction], a
-.switch
- jp CloseWindow
-
-; 37aab
-
-
-FailedBatonPass: ; 37aab
- call AnimateFailedMove
- jp PrintButItFailed
-
-; 37ab1
-
-
-ResetBatonPassStatus: ; 37ab1
-; Reset status changes that aren't passed by Baton Pass.
-
- ; Nightmare isn't passed.
- ld a, BATTLE_VARS_STATUS
- call GetBattleVar
- and SLP
- jr nz, .ok
-
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- res SUBSTATUS_NIGHTMARE, [hl]
-.ok
-
- ; Disable isn't passed.
- call ResetActorDisable
-
- ; Attraction isn't passed.
- ld hl, PlayerSubStatus1
- res SUBSTATUS_IN_LOVE, [hl]
- ld hl, EnemySubStatus1
- res SUBSTATUS_IN_LOVE, [hl]
- ld hl, PlayerSubStatus5
-
- ld a, BATTLE_VARS_SUBSTATUS5
- call GetBattleVarAddr
- res SUBSTATUS_TRANSFORMED, [hl]
- res SUBSTATUS_ENCORED, [hl]
-
- ; New mon hasn't used a move yet.
- ld a, BATTLE_VARS_LAST_MOVE
- call GetBattleVarAddr
- ld [hl], 0
-
- xor a
- ld [wPlayerWrapCount], a
- ld [wEnemyWrapCount], a
- ret
-
-; 37ae9
-
-
-CheckAnyOtherAlivePartyMons: ; 37ae9
- ld hl, PartyMon1HP
- ld a, [PartyCount]
- ld d, a
- ld a, [CurBattleMon]
- ld e, a
- jr CheckAnyOtherAliveMons
-
-; 37af6
-
-
-CheckAnyOtherAliveEnemyMons: ; 37af6
- ld hl, OTPartyMon1HP
- ld a, [OTPartyCount]
- ld d, a
- ld a, [CurOTMon]
- ld e, a
-
- ; fallthrough
-; 37b01
-
-CheckAnyOtherAliveMons: ; 37b01
-; Check for nonzero HP starting from partymon
-; HP at hl for d partymons, besides current mon e.
-
-; Return nz if any are alive.
-
- xor a
- ld b, a
- ld c, a
-.loop
- ld a, c
- cp d
- jr z, .done
- cp e
- jr z, .next
-
- ld a, [hli]
- or b
- ld b, a
- ld a, [hld]
- or b
- ld b, a
-
-.next
- push bc
- ld bc, PARTYMON_STRUCT_LENGTH
- add hl, bc
- pop bc
- inc c
- jr .loop
-
-.done
- ld a, b
- and a
- ret
-
-; 37b1d
-
-
-BattleCommand_Pursuit: ; 37b1d
-; pursuit
-; Double damage if the opponent is switching.
-
- ld hl, wEnemyIsSwitching
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld hl, wPlayerIsSwitching
-.ok
- ld a, [hl]
- and a
- ret z
-
- ld hl, CurDamage + 1
- sla [hl]
- dec hl
- rl [hl]
- ret nc
-
- ld a, $ff
- ld [hli], a
- ld [hl], a
- ret
-
-; 37b39
-
-
-BattleCommand_ClearHazards: ; 37b39
-; clearhazards
-
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- bit SUBSTATUS_LEECH_SEED, [hl]
- jr z, .not_leeched
- res SUBSTATUS_LEECH_SEED, [hl]
- ld hl, ShedLeechSeedText
- call StdBattleTextBox
-.not_leeched
-
- ld hl, PlayerScreens
- ld de, wPlayerWrapCount
- ld a, [hBattleTurn]
- and a
- jr z, .got_screens_wrap
- ld hl, EnemyScreens
- ld de, wEnemyWrapCount
-.got_screens_wrap
- bit SCREENS_SPIKES, [hl]
- jr z, .no_spikes
- res SCREENS_SPIKES, [hl]
- ld hl, BlewSpikesText
- push de
- call StdBattleTextBox
- pop de
-.no_spikes
-
- ld a, [de]
- and a
- ret z
- xor a
- ld [de], a
- ld hl, ReleasedByText
- jp StdBattleTextBox
-
-; 37b74
-
-
BattleCommand_HealMorn: ; 37b74
; healmorn
ld b, MORN_F
@@ -9352,198 +7141,19 @@
; 37be8
-BattleCommand_HiddenPower: ; 37be8
-; hiddenpower
+INCLUDE "engine/battle/move_effects/hidden_power.asm"
- ld a, [AttackMissed]
- and a
- ret nz
- farcall HiddenPowerDamage
- ret
+INCLUDE "engine/battle/move_effects/rain_dance.asm"
-; 37bf4
+INCLUDE "engine/battle/move_effects/sunny_day.asm"
+INCLUDE "engine/battle/move_effects/belly_drum.asm"
-BattleCommand_StartRain: ; 37bf4
-; startrain
- ld a, WEATHER_RAIN
- ld [Weather], a
- ld a, 5
- ld [WeatherCount], a
- call AnimateCurrentMove
- ld hl, DownpourText
- jp StdBattleTextBox
+INCLUDE "engine/battle/move_effects/psych_up.asm"
+
+INCLUDE "engine/battle/move_effects/mirror_coat.asm"
-; 37c07
-
-BattleCommand_StartSun: ; 37c07
-; startsun
- ld a, WEATHER_SUN
- ld [Weather], a
- ld a, 5
- ld [WeatherCount], a
- call AnimateCurrentMove
- ld hl, SunGotBrightText
- jp StdBattleTextBox
-
-; 37c1a
-
-
-BattleCommand_BellyDrum: ; 37c1a
-; bellydrum
-; This command is buggy because it raises the user's attack
-; before checking that it has enough HP to use the move.
-; Swap the order of these two blocks to fix.
- call BattleCommand_AttackUp2
- ld a, [AttackMissed]
- and a
- jr nz, .failed
-
- callfar GetHalfMaxHP
- callfar CheckUserHasEnoughHP
- jr nc, .failed
-
- push bc
- call AnimateCurrentMove
- pop bc
- callfar SubtractHPFromUser
- call UpdateUserInParty
- ld a, 5
-
-.max_attack_loop
- push af
- call BattleCommand_AttackUp2
- pop af
- dec a
- jr nz, .max_attack_loop
-
- ld hl, BellyDrumText
- jp StdBattleTextBox
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-
-; 37c55
-
-
-BattleCommand_PsychUp: ; 37c55
-; psychup
-
- ld hl, EnemyStatLevels
- ld de, PlayerStatLevels
- ld a, [hBattleTurn]
- and a
- jr z, .pointers_correct
-; It's the enemy's turn, so swap the pointers.
- push hl
- ld h, d
- ld l, e
- pop de
-.pointers_correct
- push hl
- ld b, NUM_LEVEL_STATS
-; If any of the enemy's stats is modified from its base level,
-; the move succeeds. Otherwise, it fails.
-.loop
- ld a, [hli]
- cp BASE_STAT_LEVEL
- jr nz, .break
- dec b
- jr nz, .loop
- pop hl
- call AnimateFailedMove
- jp PrintButItFailed
-
-.break
- pop hl
- ld b, NUM_LEVEL_STATS
-.loop2
- ld a, [hli]
- ld [de], a
- inc de
- dec b
- jr nz, .loop2
- ld a, [hBattleTurn]
- and a
- jr nz, .calc_enemy_stats
- call CalcPlayerStats
- jr .merge
-
-.calc_enemy_stats
- call CalcEnemyStats
-.merge
- call AnimateCurrentMove
- ld hl, CopiedStatsText
- jp StdBattleTextBox
-
-; 37c95
-
-
-BattleCommand_MirrorCoat: ; 37c95
-; mirrorcoat
-
- ld a, 1
- ld [AttackMissed], a
-
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- ret z
-
- ld b, a
- callfar GetMoveEffect
- ld a, b
- cp EFFECT_MIRROR_COAT
- ret z
-
- call BattleCommand_ResetTypeMatchup
- ld a, [wTypeMatchup]
- and a
- ret z
-
- call CheckOpponentWentFirst
- ret z
-
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- dec a
- ld de, StringBuffer1
- call GetMoveData
-
- ld a, [StringBuffer1 + 2]
- and a
- ret z
-
- ld a, [StringBuffer1 + 3]
- cp SPECIAL
- ret c
-
- ld hl, CurDamage
- ld a, [hli]
- or [hl]
- ret z
-
- ld a, [hl]
- add a
- ld [hld], a
- ld a, [hl]
- adc a
- ld [hl], a
- jr nc, .capped
- ld a, $ff
- ld [hli], a
- ld [hl], a
-.capped
-
- xor a
- ld [AttackMissed], a
- ret
-
-; 37ce6
-
-
BattleCommand_DoubleMinimizeDamage: ; 37ce6
; doubleminimizedamage
@@ -9580,115 +7190,11 @@
; 37d0d
-BattleCommand_CheckFutureSight: ; 37d0d
-; checkfuturesight
+INCLUDE "engine/battle/move_effects/future_sight.asm"
- ld hl, wPlayerFutureSightCount
- ld de, wPlayerFutureSightDamage
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld hl, wEnemyFutureSightCount
- ld de, wEnemyFutureSightDamage
-.ok
+INCLUDE "engine/battle/move_effects/thunder.asm"
- ld a, [hl]
- and a
- ret z
- cp 1
- ret nz
- ld [hl], 0
- ld a, [de]
- inc de
- ld [CurDamage], a
- ld a, [de]
- ld [CurDamage + 1], a
- ld b, futuresight_command
- jp SkipToBattleCommand
-
-; 37d34
-
-BattleCommand_FutureSight: ; 37d34
-; futuresight
-
- call CheckUserIsCharging
- jr nz, .AlreadyChargingFutureSight
- ld a, BATTLE_VARS_MOVE_ANIM
- call GetBattleVar
- ld b, a
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE
- call GetBattleVarAddr
- ld [hl], b
- ld a, BATTLE_VARS_LAST_MOVE
- call GetBattleVarAddr
- ld [hl], b
-.AlreadyChargingFutureSight:
- ld hl, wPlayerFutureSightCount
- ld a, [hBattleTurn]
- and a
- jr z, .GotFutureSightCount
- ld hl, wEnemyFutureSightCount
-.GotFutureSightCount:
- ld a, [hl]
- and a
- jr nz, .failed
- ld a, 4
- ld [hl], a
- call BattleCommand_LowerSub
- call BattleCommand_MoveDelay
- ld hl, ForesawAttackText
- call StdBattleTextBox
- call BattleCommand_RaiseSub
- ld de, wPlayerFutureSightDamage
- ld a, [hBattleTurn]
- and a
- jr z, .StoreDamage
- ld de, wEnemyFutureSightDamage
-.StoreDamage:
- ld hl, CurDamage
- ld a, [hl]
- ld [de], a
- ld [hl], 0
- inc hl
- inc de
- ld a, [hl]
- ld [de], a
- ld [hl], 0
- jp EndMoveEffect
-
-.failed
- pop bc
- call ResetDamage
- call AnimateFailedMove
- call PrintButItFailed
- jp EndMoveEffect
-
-; 37d94
-
-
-BattleCommand_ThunderAccuracy: ; 37d94
-; thunderaccuracy
-
- ld a, BATTLE_VARS_MOVE_TYPE
- call GetBattleVarAddr
- inc hl
- ld a, [Weather]
- cp WEATHER_RAIN
- jr z, .rain
- cp WEATHER_SUN
- ret nz
- ld [hl], 50 percent + 1
- ret
-
-.rain
- ; Redundant with CheckHit guranteeing hit
- ld [hl], 100 percent
- ret
-
-; 37daa
-
-
CheckHiddenOpponent: ; 37daa
; BUG: This routine should account for Lock-On and Mind Reader.
ld a, BATTLE_VARS_SUBSTATUS3_OPP
@@ -9828,7 +7334,6 @@
LoadAnim: ; 37e44
-
ld [FXAnimID], a
; fallthrough
--- a/engine/battle/effect_commands/attract.asm
+++ /dev/null
@@ -1,79 +1,0 @@
-BattleCommand_Attract: ; 377ce
-; attract
- ld a, [AttackMissed]
- and a
- jr nz, .failed
- call CheckOppositeGender
- jr c, .failed
- call CheckHiddenOpponent
- jr nz, .failed
- ld a, BATTLE_VARS_SUBSTATUS1_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_IN_LOVE, [hl]
- jr nz, .failed
-
- set SUBSTATUS_IN_LOVE, [hl]
- call AnimateCurrentMove
-
-; 'fell in love!'
- ld hl, FellInLoveText
- jp StdBattleTextBox
-
-.failed
- jp FailAttract
-; 377f5
-
-
-CheckOppositeGender: ; 377f5
- ld a, MON_SPECIES
- call BattlePartyAttr
- ld a, [hl]
- ld [CurPartySpecies], a
-
- ld a, [CurBattleMon]
- ld [CurPartyMon], a
- xor a
- ld [MonType], a
-
- farcall GetGender
- jr c, .genderless_samegender
-
- ld b, 1
- jr nz, .got_gender
- dec b
-
-.got_gender
- push bc
- ld a, [TempEnemyMonSpecies]
- ld [CurPartySpecies], a
- ld hl, EnemyMonDVs
- ld a, [EnemySubStatus5]
- bit SUBSTATUS_TRANSFORMED, a
- jr z, .not_transformed
- ld hl, wEnemyBackupDVs
-.not_transformed
- ld a, [hli]
- ld [TempMonDVs], a
- ld a, [hl]
- ld [TempMonDVs + 1], a
- ld a, 3
- ld [MonType], a
- farcall GetGender
- pop bc
- jr c, .genderless_samegender
-
- ld a, 1
- jr nz, .got_enemy_gender
- dec a
-
-.got_enemy_gender
- xor b
- jr z, .genderless_samegender
-
- and a
- ret
-
-.genderless_samegender
- scf
- ret
-; 3784b
--- a/engine/battle/effect_commands/curse.asm
+++ /dev/null
@@ -1,97 +1,0 @@
-BattleCommand_Curse: ; 37588
-; curse
-
- ld de, BattleMonType1
- ld bc, PlayerStatLevels
- ld a, [hBattleTurn]
- and a
- jr z, .go
- ld de, EnemyMonType1
- ld bc, EnemyStatLevels
-
-.go
-
-; Curse is different for Ghost-types.
-
- ld a, [de]
- cp GHOST
- jr z, .ghost
- inc de
- ld a, [de]
- cp GHOST
- jr z, .ghost
-
-
-; If no stats can be increased, don't.
-
-; Attack
- ld a, [bc]
- cp MAX_STAT_LEVEL
- jr c, .raise
-
-; Defense
- inc bc
- ld a, [bc]
- cp MAX_STAT_LEVEL
- jr nc, .cantraise
-
-.raise
-
-; Raise Attack and Defense, and lower Speed.
-
- ld a, $1
- ld [wKickCounter], a
- call AnimateCurrentMove
- ld a, SPEED
- call LowerStat
- call BattleCommand_SwitchTurn
- call BattleCommand_StatDownMessage
- call ResetMiss
- call BattleCommand_SwitchTurn
- call BattleCommand_AttackUp
- call BattleCommand_StatUpMessage
- call ResetMiss
- call BattleCommand_DefenseUp
- jp BattleCommand_StatUpMessage
-
-
-.ghost
-
-; Cut HP in half and put a curse on the opponent.
-
- call CheckHiddenOpponent
- jr nz, .failed
-
- call CheckSubstituteOpp
- jr nz, .failed
-
- ld a, BATTLE_VARS_SUBSTATUS1_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_CURSE, [hl]
- jr nz, .failed
-
- set SUBSTATUS_CURSE, [hl]
- call AnimateCurrentMove
- ld hl, GetHalfMaxHP
- call CallBattleCore
- ld hl, SubtractHPFromUser
- call CallBattleCore
- call UpdateUserInParty
- ld hl, PutACurseText
- jp StdBattleTextBox
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-
-
-.cantraise
-
-; Can't raise either stat.
-
- ld b, ABILITY + 1
- call GetStatName
- call AnimateFailedMove
- ld hl, WontRiseAnymoreText
- jp StdBattleTextBox
-; 37618
--- a/engine/battle/effect_commands/endure.asm
+++ /dev/null
@@ -1,17 +1,0 @@
-BattleCommand_Endure: ; 3766f
-; endure
-
-; Endure shares code with Protect. See protect.asm.
-
- call ProtectChance
- ret c
-
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- set SUBSTATUS_ENDURE, [hl]
-
- call AnimateCurrentMove
-
- ld hl, BracedItselfText
- jp StdBattleTextBox
-; 37683
--- a/engine/battle/effect_commands/foresight.asm
+++ /dev/null
@@ -1,23 +1,0 @@
-BattleCommand_Foresight: ; 376a0
-; foresight
-
- ld a, [AttackMissed]
- and a
- jr nz, .failed
-
- call CheckHiddenOpponent
- jr nz, .failed
-
- ld a, BATTLE_VARS_SUBSTATUS1_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_IDENTIFIED, [hl]
- jr nz, .failed
-
- set SUBSTATUS_IDENTIFIED, [hl]
- call AnimateCurrentMove
- ld hl, IdentifiedText
- jp StdBattleTextBox
-
-.failed
- jp FailForesight
-; 376c2
--- a/engine/battle/effect_commands/metronome.asm
+++ /dev/null
@@ -1,46 +1,0 @@
-BattleCommand_Metronome: ; 37418
-; metronome
-
- call ClearLastMove
- call CheckUserIsCharging
- jr nz, .asm_3742b
-
- ld a, [wKickCounter]
- push af
- call BattleCommand_LowerSub
- pop af
- ld [wKickCounter], a
-
-.asm_3742b
- call LoadMoveAnim
-
-.GetMove:
- call BattleRandom
-
-; No invalid moves.
- cp NUM_ATTACKS + 1
- jr nc, .GetMove
-
-; None of the moves in MetronomeExcepts.
- push af
- ld de, 1
- ld hl, MetronomeExcepts
- call IsInArray
- pop bc
- jr c, .GetMove
-
-; No moves the user already has.
- ld a, b
- call CheckUserMove
- jr z, .GetMove
-
-
- ld a, BATTLE_VARS_MOVE
- call GetBattleVarAddr
- ld [hl], b
- call UpdateMoveData
- jp ResetTurn
-; 37454
-
-
-INCLUDE "data/battle/metronome_exception_moves.asm"
--- a/engine/battle/effect_commands/mirror_move.asm
+++ /dev/null
@@ -1,52 +1,0 @@
-BattleCommand_MirrorMove: ; 373c9
-; mirrormove
-
- call ClearLastMove
-
- ld a, BATTLE_VARS_MOVE
- call GetBattleVarAddr
-
- ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
- call GetBattleVar
- and a
- jr z, .failed
-
- call CheckUserMove
- jr nz, .use
-
-.failed
- call AnimateFailedMove
-
- ld hl, MirrorMoveFailedText
- call StdBattleTextBox
- jp EndMoveEffect
-
-.use
- ld a, b
- ld [hl], a
- ld [wd265], a
-
- push af
- ld a, BATTLE_VARS_MOVE_ANIM
- call GetBattleVarAddr
- ld d, h
- ld e, l
- pop af
-
- dec a
- call GetMoveData
- call GetMoveName
- call CopyName1
- call CheckUserIsCharging
- jr nz, .done
-
- ld a, [wKickCounter]
- push af
- call BattleCommand_LowerSub
- pop af
- ld [wKickCounter], a
-
-.done
- call BattleCommand_MoveDelay
- jp ResetTurn
-; 37418
--- a/engine/battle/effect_commands/nightmare.asm
+++ /dev/null
@@ -1,38 +1,0 @@
-BattleCommand_Nightmare: ; 37536
-; nightmare
-
-; Can't hit an absent opponent.
-
- call CheckHiddenOpponent
- jr nz, .failed
-
-; Can't hit a substitute.
-
- call CheckSubstituteOpp
- jr nz, .failed
-
-; Only works on a sleeping opponent.
-
- ld a, BATTLE_VARS_STATUS_OPP
- call GetBattleVarAddr
- and SLP
- jr z, .failed
-
-; Bail if the opponent is already having a nightmare.
-
- ld a, BATTLE_VARS_SUBSTATUS1_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_NIGHTMARE, [hl]
- jr nz, .failed
-
-; Otherwise give the opponent a nightmare.
-
- set SUBSTATUS_NIGHTMARE, [hl]
- call AnimateCurrentMove
- ld hl, StartedNightmareText
- jp StdBattleTextBox
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-; 37563
--- a/engine/battle/effect_commands/perish_song.asm
+++ /dev/null
@@ -1,40 +1,0 @@
-BattleCommand_PerishSong: ; 376c2
-; perishsong
-
-
- ld hl, PlayerSubStatus1
- ld de, EnemySubStatus1
- bit SUBSTATUS_PERISH, [hl]
- jr z, .ok
-
- ld a, [de]
- bit SUBSTATUS_PERISH, a
- jr nz, .failed
-
-.ok
- bit SUBSTATUS_PERISH, [hl]
- jr nz, .enemy
-
- set SUBSTATUS_PERISH, [hl]
- ld a, 4
- ld [PlayerPerishCount], a
-
-.enemy
- ld a, [de]
- bit SUBSTATUS_PERISH, a
- jr nz, .done
-
- set SUBSTATUS_PERISH, a
- ld [de], a
- ld a, 4
- ld [EnemyPerishCount], a
-
-.done
- call AnimateCurrentMove
- ld hl, StartPerishText
- jp StdBattleTextBox
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-; 376f8
--- a/engine/battle/effect_commands/present.asm
+++ /dev/null
@@ -1,88 +1,0 @@
-BattleCommand_Present: ; 37874
-; present
-
- ld a, [wLinkMode]
- cp LINK_COLOSSEUM
- jr z, .colosseum_skippush
- push bc
- push de
-.colosseum_skippush
-
- call BattleCommand_Stab
-
- ld a, [wLinkMode]
- cp LINK_COLOSSEUM
- jr z, .colosseum_skippop
- pop de
- pop bc
-.colosseum_skippop
-
- ld a, [wTypeMatchup]
- and a
- jp z, AnimateFailedMove
- ld a, [AttackMissed]
- and a
- jp nz, AnimateFailedMove
-
- push bc
- call BattleRandom
- ld b, a
- ld hl, PresentPower
- ld c, 0
-.next
- ld a, [hli]
- cp -1
- jr z, .heal_effect ; 378a4 $11
- cp b
- jr nc, .got_power ; 378a7 $4
- inc c
- inc hl
- jr .next ; 378ab $f4
-
-.got_power
- ld a, c
- ld [wPresentPower], a
- call AnimateCurrentMoveEitherSide
- ld d, [hl]
- pop bc
- ret
-
-.heal_effect
- pop bc
- ld a, 3
- ld [wPresentPower], a
- call AnimateCurrentMove
- call BattleCommand_SwitchTurn
- ld hl, AICheckPlayerMaxHP
- ld a, [hBattleTurn]
- and a
- jr z, .got_hp_fn_pointer ; 378c9 $3
- ld hl, AICheckEnemyMaxHP
-.got_hp_fn_pointer
- ld a, BANK(AICheckPlayerMaxHP)
- rst FarCall
- jr c, .already_fully_healed ; 378d1 $20
-
- ld hl, GetQuarterMaxHP
- call CallBattleCore
- call BattleCommand_SwitchTurn
- ld hl, RestoreHP
- call CallBattleCore
- call BattleCommand_SwitchTurn
- ld hl, RegainedHealthText
- call StdBattleTextBox
- call BattleCommand_SwitchTurn
- call UpdateOpponentInParty
- jr .do_animation ; 378f1 $11
-
-.already_fully_healed
- call BattleCommand_SwitchTurn
- call _CheckBattleScene
- jr nc, .do_animation ; 378f9 $9
- call AnimateFailedMove
- ld hl, RefusedGiftText
- call StdBattleTextBox
-.do_animation
- jp EndMoveEffect
-
-INCLUDE "data/moves/present_power.asm"
--- a/engine/battle/effect_commands/protect.asm
+++ /dev/null
@@ -1,80 +1,0 @@
-BattleCommand_Protect: ; 37618
-; protect
- call ProtectChance
- ret c
-
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- set SUBSTATUS_PROTECT, [hl]
-
- call AnimateCurrentMove
-
- ld hl, ProtectedItselfText
- jp StdBattleTextBox
-; 3762c
-
-
-ProtectChance: ; 3762c
-
- ld de, PlayerProtectCount
- ld a, [hBattleTurn]
- and a
- jr z, .asm_37637
- ld de, EnemyProtectCount
-.asm_37637
-
- call CheckOpponentWentFirst
- jr nz, .failed
-
-; Can't have a substitute.
-
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVar
- bit SUBSTATUS_SUBSTITUTE, a
- jr nz, .failed
-
-; Halve the chance of a successful Protect for each consecutive use.
-
- ld b, $ff
- ld a, [de]
- ld c, a
-.loop
- ld a, c
- and a
- jr z, .done
- dec c
-
- srl b
- ld a, b
- and a
- jr nz, .loop
- jr .failed
-.done
-
-.rand
- call BattleRandom
- and a
- jr z, .rand
-
- dec a
- cp b
- jr nc, .failed
-
-; Another consecutive Protect use.
-
- ld a, [de]
- inc a
- ld [de], a
-
- and a
- ret
-
-
-.failed
- xor a
- ld [de], a
- call AnimateFailedMove
- call PrintButItFailed
- scf
- ret
-; 3766f
--- a/engine/battle/effect_commands/rollout.asm
+++ /dev/null
@@ -1,99 +1,0 @@
-MAX_ROLLOUT_COUNT EQU 5
-
-
-BattleCommand_CheckCurl: ; 37718
-; checkcurl
-
- ld de, PlayerRolloutCount
- ld a, [hBattleTurn]
- and a
- jr z, .ok
- ld de, EnemyRolloutCount
-.ok
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVar
- bit SUBSTATUS_ROLLOUT, a
- jr z, .reset
-
- ld b, $4 ; doturn
- jp SkipToBattleCommand
-
-.reset
- xor a
- ld [de], a
- ret
-; 37734
-
-
-BattleCommand_RolloutPower: ; 37734
-; rolloutpower
-
- ld a, BATTLE_VARS_STATUS
- call GetBattleVar
- and SLP
- ret nz
-
- ld hl, PlayerRolloutCount
- ld a, [hBattleTurn]
- and a
- jr z, .got_rollout_count
- ld hl, EnemyRolloutCount
-
-.got_rollout_count
- ld a, [hl]
- and a
- jr nz, .skip_set_rampage
- ld a, 1
- ld [wSomeoneIsRampaging], a
-
-.skip_set_rampage
- ld a, [AttackMissed]
- and a
- jr z, .hit
-
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- res 6, [hl]
- ret
-
-.hit
- inc [hl]
- ld a, [hl]
- ld b, a
- cp MAX_ROLLOUT_COUNT
- jr c, .not_done_with_rollout
-
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- res SUBSTATUS_ROLLOUT, [hl]
- jr .done_with_substatus_flag
-
-.not_done_with_rollout
- ld a, BATTLE_VARS_SUBSTATUS1
- call GetBattleVarAddr
- set SUBSTATUS_ROLLOUT, [hl]
-
-.done_with_substatus_flag
- ld a, BATTLE_VARS_SUBSTATUS2
- call GetBattleVar
- bit SUBSTATUS_CURLED, a
- jr z, .not_curled
- inc b
-.not_curled
-.loop
- dec b
- jr z, .done_damage
-
- ld hl, CurDamage + 1
- sla [hl]
- dec hl
- rl [hl]
- jr nc, .loop
-
- ld a, $ff
- ld [hli], a
- ld [hl], a
-
-.done_damage
- ret
-; 37791
--- a/engine/battle/effect_commands/sandstorm.asm
+++ /dev/null
@@ -1,19 +1,0 @@
-BattleCommand_StartSandstorm: ; 376f8
-; startsandstorm
-
- ld a, [Weather]
- cp WEATHER_SANDSTORM
- jr z, .failed
-
- ld a, WEATHER_SANDSTORM
- ld [Weather], a
- ld a, 5
- ld [WeatherCount], a
- call AnimateCurrentMove
- ld hl, SandstormBrewedText
- jp StdBattleTextBox
-
-.failed
- call AnimateFailedMove
- jp PrintButItFailed
-; 37718
--- a/engine/battle/effect_commands/spikes.asm
+++ /dev/null
@@ -1,27 +1,0 @@
-BattleCommand_Spikes: ; 37683
-; spikes
-
- ld hl, EnemyScreens
- ld a, [hBattleTurn]
- and a
- jr z, .asm_3768e
- ld hl, PlayerScreens
-.asm_3768e
-
-; Fails if spikes are already down!
-
- bit SCREENS_SPIKES, [hl]
- jr nz, .failed
-
-; Nothing else stops it from working.
-
- set SCREENS_SPIKES, [hl]
-
- call AnimateCurrentMove
-
- ld hl, SpikesText
- jp StdBattleTextBox
-
-.failed
- jp FailSpikes
-; 376a0
--- a/engine/battle/effect_commands/thief.asm
+++ /dev/null
@@ -1,116 +1,0 @@
-BattleCommand_Thief: ; 37492
-; thief
-
- ld a, [hBattleTurn]
- and a
- jr nz, .enemy
-
-; The player needs to be able to steal an item.
-
- call .playeritem
- ld a, [hl]
- and a
- ret nz
-
-; The enemy needs to have an item to steal.
-
- call .enemyitem
- ld a, [hl]
- and a
- ret z
-
-; Can't steal mail.
-
- ld [wd265], a
- ld d, a
- farcall ItemIsMail
- ret c
-
- ld a, [EffectFailed]
- and a
- ret nz
-
- ld a, [wLinkMode]
- and a
- jr z, .stealenemyitem
-
- ld a, [wBattleMode]
- dec a
- ret z
-
-.stealenemyitem
- call .enemyitem
- xor a
- ld [hl], a
- ld [de], a
-
- call .playeritem
- ld a, [wd265]
- ld [hl], a
- ld [de], a
- jr .stole
-
-
-.enemy
-
-; The enemy can't already have an item.
-
- call .enemyitem
- ld a, [hl]
- and a
- ret nz
-
-; The player must have an item to steal.
-
- call .playeritem
- ld a, [hl]
- and a
- ret z
-
-; Can't steal mail!
-
- ld [wd265], a
- ld d, a
- farcall ItemIsMail
- ret c
-
- ld a, [EffectFailed]
- and a
- ret nz
-
-; If the enemy steals your item,
-; it's gone for good if you don't get it back.
-
- call .playeritem
- xor a
- ld [hl], a
- ld [de], a
-
- call .enemyitem
- ld a, [wd265]
- ld [hl], a
- ld [de], a
-
-
-.stole
- call GetItemName
- ld hl, StoleText
- jp StdBattleTextBox
-
-
-.playeritem
- ld a, 1
- call BattlePartyAttr
- ld d, h
- ld e, l
- ld hl, BattleMonItem
- ret
-
-.enemyitem
- ld a, 1
- call OTPartyAttr
- ld d, h
- ld e, l
- ld hl, EnemyMonItem
- ret
-; 37517
--- a/engine/battle/effect_commands/transform.asm
+++ /dev/null
@@ -1,141 +1,0 @@
-
-BattleCommand_Transform: ; 371cd
-; transform
-
- call ClearLastMove
- ld a, BATTLE_VARS_SUBSTATUS5_OPP
- call GetBattleVarAddr
- bit SUBSTATUS_TRANSFORMED, [hl]
- jp nz, BattleEffect_ButItFailed
- call CheckHiddenOpponent
- jp nz, BattleEffect_ButItFailed
- xor a
- ld [wNumHits], a
- ld [FXAnimID + 1], a
- ld a, $1
- ld [wKickCounter], a
- ld a, BATTLE_VARS_SUBSTATUS4
- call GetBattleVarAddr
- bit SUBSTATUS_SUBSTITUTE, [hl]
- push af
- jr z, .mimic_substitute
- call CheckUserIsCharging
- jr nz, .mimic_substitute
- ld a, SUBSTITUTE
- call LoadAnim
-.mimic_substitute
- ld a, BATTLE_VARS_SUBSTATUS5
- call GetBattleVarAddr
- set SUBSTATUS_TRANSFORMED, [hl]
- call ResetActorDisable
- ld hl, BattleMonSpecies
- ld de, EnemyMonSpecies
- ld a, [hBattleTurn]
- and a
- jr nz, .got_mon_species
- ld hl, EnemyMonSpecies
- ld de, BattleMonSpecies
- xor a
- ld [CurMoveNum], a
-.got_mon_species
- push hl
- ld a, [hli]
- ld [de], a
- inc hl
- inc de
- inc de
- ld bc, NUM_MOVES
- call CopyBytes
- ld a, [hBattleTurn]
- and a
- jr z, .mimic_enemy_backup
- ld a, [de]
- ld [wEnemyBackupDVs], a
- inc de
- ld a, [de]
- ld [wEnemyBackupDVs + 1], a
- dec de
-.mimic_enemy_backup
-; copy DVs
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- inc de
-; move pointer to stats
- ld bc, BattleMonStats - BattleMonPP
- add hl, bc
- push hl
- ld h, d
- ld l, e
- add hl, bc
- ld d, h
- ld e, l
- pop hl
- ld bc, BattleMonStructEnd - BattleMonStats
- call CopyBytes
-; init the power points
- ld bc, BattleMonMoves - BattleMonStructEnd
- add hl, bc
- push de
- ld d, h
- ld e, l
- pop hl
- ld bc, BattleMonPP - BattleMonStructEnd
- add hl, bc
- ld b, NUM_MOVES
-.pp_loop
- ld a, [de]
- inc de
- and a
- jr z, .done_move
- cp SKETCH
- ld a, 1
- jr z, .done_move
- ld a, 5
-.done_move
- ld [hli], a
- dec b
- jr nz, .pp_loop
- pop hl
- ld a, [hl]
- ld [wNamedObjectIndexBuffer], a
- call GetPokemonName
- ld hl, EnemyStats
- ld de, PlayerStats
- ld bc, 2 * 5
- call BattleSideCopy
- ld hl, EnemyStatLevels
- ld de, PlayerStatLevels
- ld bc, 8
- call BattleSideCopy
- call _CheckBattleScene
- jr c, .mimic_anims
- ld a, [hBattleTurn]
- and a
- ld a, [wPlayerMinimized]
- jr z, .got_byte
- ld a, [wEnemyMinimized]
-.got_byte
- and a
- jr nz, .mimic_anims
- call LoadMoveAnim
- jr .after_anim
-
-.mimic_anims
- call BattleCommand_MoveDelay
- call BattleCommand_RaiseSubNoAnim
-.after_anim
- xor a
- ld [wNumHits], a
- ld [FXAnimID + 1], a
- ld a, $2
- ld [wKickCounter], a
- pop af
- ld a, SUBSTITUTE
- call nz, LoadAnim
- ld hl, TransformedText
- jp StdBattleTextBox
-
-; 372c6
--- /dev/null
+++ b/engine/battle/move_effects/attract.asm
@@ -1,0 +1,79 @@
+BattleCommand_Attract: ; 377ce
+; attract
+ ld a, [AttackMissed]
+ and a
+ jr nz, .failed
+ call CheckOppositeGender
+ jr c, .failed
+ call CheckHiddenOpponent
+ jr nz, .failed
+ ld a, BATTLE_VARS_SUBSTATUS1_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_IN_LOVE, [hl]
+ jr nz, .failed
+
+ set SUBSTATUS_IN_LOVE, [hl]
+ call AnimateCurrentMove
+
+; 'fell in love!'
+ ld hl, FellInLoveText
+ jp StdBattleTextBox
+
+.failed
+ jp FailMove
+; 377f5
+
+
+CheckOppositeGender: ; 377f5
+ ld a, MON_SPECIES
+ call BattlePartyAttr
+ ld a, [hl]
+ ld [CurPartySpecies], a
+
+ ld a, [CurBattleMon]
+ ld [CurPartyMon], a
+ xor a
+ ld [MonType], a
+
+ farcall GetGender
+ jr c, .genderless_samegender
+
+ ld b, 1
+ jr nz, .got_gender
+ dec b
+
+.got_gender
+ push bc
+ ld a, [TempEnemyMonSpecies]
+ ld [CurPartySpecies], a
+ ld hl, EnemyMonDVs
+ ld a, [EnemySubStatus5]
+ bit SUBSTATUS_TRANSFORMED, a
+ jr z, .not_transformed
+ ld hl, wEnemyBackupDVs
+.not_transformed
+ ld a, [hli]
+ ld [TempMonDVs], a
+ ld a, [hl]
+ ld [TempMonDVs + 1], a
+ ld a, 3
+ ld [MonType], a
+ farcall GetGender
+ pop bc
+ jr c, .genderless_samegender
+
+ ld a, 1
+ jr nz, .got_enemy_gender
+ dec a
+
+.got_enemy_gender
+ xor b
+ jr z, .genderless_samegender
+
+ and a
+ ret
+
+.genderless_samegender
+ scf
+ ret
+; 3784b
--- /dev/null
+++ b/engine/battle/move_effects/baton_pass.asm
@@ -1,0 +1,241 @@
+BattleCommand_BatonPass: ; 379c9
+; batonpass
+
+ ld a, [hBattleTurn]
+ and a
+ jp nz, .Enemy
+
+
+; Need something to switch to
+ call CheckAnyOtherAlivePartyMons
+ jp z, FailedBatonPass
+
+ call UpdateBattleMonInParty
+ call AnimateCurrentMove
+
+ ld c, 50
+ call DelayFrames
+
+; Transition into switchmon menu
+ call LoadStandardMenuHeader
+ farcall SetUpBattlePartyMenu_NoLoop
+
+ farcall ForcePickSwitchMonInBattle
+
+; Return to battle scene
+ call ClearPalettes
+ farcall _LoadBattleFontsHPBar
+ call CloseWindow
+ call ClearSprites
+ hlcoord 1, 0
+ lb bc, 4, 10
+ call ClearBox
+ ld b, SCGB_BATTLE_COLORS
+ call GetSGBLayout
+ call SetPalettes
+ call BatonPass_LinkPlayerSwitch
+
+; Mobile link battles handle entrances differently
+ farcall CheckMobileBattleError
+ jp c, EndMoveEffect
+
+ ld hl, PassedBattleMonEntrance
+ call CallBattleCore
+
+ call ResetBatonPassStatus
+ ret
+
+
+.Enemy:
+
+; Wildmons don't have anything to switch to
+ ld a, [wBattleMode]
+ dec a ; WILDMON
+ jp z, FailedBatonPass
+
+ call CheckAnyOtherAliveEnemyMons
+ jp z, FailedBatonPass
+
+ call UpdateEnemyMonInParty
+ call AnimateCurrentMove
+ call BatonPass_LinkEnemySwitch
+
+; Mobile link battles handle entrances differently
+ farcall CheckMobileBattleError
+ jp c, EndMoveEffect
+
+; Passed enemy PartyMon entrance
+ xor a
+ ld [wEnemySwitchMonIndex], a
+ ld hl, EnemySwitch_SetMode
+ call CallBattleCore
+ ld hl, ResetBattleParticipants
+ call CallBattleCore
+ ld a, 1
+ ld [wTypeMatchup], a
+ ld hl, ApplyStatLevelMultiplierOnAllStats
+ call CallBattleCore
+
+ ld hl, SpikesDamage
+ call CallBattleCore
+
+ jr ResetBatonPassStatus
+
+; 37a67
+
+
+BatonPass_LinkPlayerSwitch: ; 37a67
+ ld a, [wLinkMode]
+ and a
+ ret z
+
+ ld a, 1
+ ld [wPlayerAction], a
+
+ call LoadStandardMenuHeader
+ ld hl, LinkBattleSendReceiveAction
+ call CallBattleCore
+ call CloseWindow
+
+ xor a
+ ld [wPlayerAction], a
+ ret
+
+; 37a82
+
+
+BatonPass_LinkEnemySwitch: ; 37a82
+ ld a, [wLinkMode]
+ and a
+ ret z
+
+ call LoadStandardMenuHeader
+ ld hl, LinkBattleSendReceiveAction
+ call CallBattleCore
+
+ ld a, [OTPartyCount]
+ add BATTLEACTION_SWITCH1
+ ld b, a
+ ld a, [wBattleAction]
+ cp BATTLEACTION_SWITCH1
+ jr c, .baton_pass
+ cp b
+ jr c, .switch
+
+.baton_pass
+ ld a, [CurOTMon]
+ add BATTLEACTION_SWITCH1
+ ld [wBattleAction], a
+.switch
+ jp CloseWindow
+
+; 37aab
+
+
+FailedBatonPass: ; 37aab
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+; 37ab1
+
+
+ResetBatonPassStatus: ; 37ab1
+; Reset status changes that aren't passed by Baton Pass.
+
+ ; Nightmare isn't passed.
+ ld a, BATTLE_VARS_STATUS
+ call GetBattleVar
+ and SLP
+ jr nz, .ok
+
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ res SUBSTATUS_NIGHTMARE, [hl]
+.ok
+
+ ; Disable isn't passed.
+ call ResetActorDisable
+
+ ; Attraction isn't passed.
+ ld hl, PlayerSubStatus1
+ res SUBSTATUS_IN_LOVE, [hl]
+ ld hl, EnemySubStatus1
+ res SUBSTATUS_IN_LOVE, [hl]
+ ld hl, PlayerSubStatus5
+
+ ld a, BATTLE_VARS_SUBSTATUS5
+ call GetBattleVarAddr
+ res SUBSTATUS_TRANSFORMED, [hl]
+ res SUBSTATUS_ENCORED, [hl]
+
+ ; New mon hasn't used a move yet.
+ ld a, BATTLE_VARS_LAST_MOVE
+ call GetBattleVarAddr
+ ld [hl], 0
+
+ xor a
+ ld [wPlayerWrapCount], a
+ ld [wEnemyWrapCount], a
+ ret
+
+; 37ae9
+
+
+CheckAnyOtherAlivePartyMons: ; 37ae9
+ ld hl, PartyMon1HP
+ ld a, [PartyCount]
+ ld d, a
+ ld a, [CurBattleMon]
+ ld e, a
+ jr CheckAnyOtherAliveMons
+
+; 37af6
+
+
+CheckAnyOtherAliveEnemyMons: ; 37af6
+ ld hl, OTPartyMon1HP
+ ld a, [OTPartyCount]
+ ld d, a
+ ld a, [CurOTMon]
+ ld e, a
+
+ ; fallthrough
+; 37b01
+
+CheckAnyOtherAliveMons: ; 37b01
+; Check for nonzero HP starting from partymon
+; HP at hl for d partymons, besides current mon e.
+
+; Return nz if any are alive.
+
+ xor a
+ ld b, a
+ ld c, a
+.loop
+ ld a, c
+ cp d
+ jr z, .done
+ cp e
+ jr z, .next
+
+ ld a, [hli]
+ or b
+ ld b, a
+ ld a, [hld]
+ or b
+ ld b, a
+
+.next
+ push bc
+ ld bc, PARTYMON_STRUCT_LENGTH
+ add hl, bc
+ pop bc
+ inc c
+ jr .loop
+
+.done
+ ld a, b
+ and a
+ ret
+
+; 37b1d
--- /dev/null
+++ b/engine/battle/move_effects/beat_up.asm
@@ -1,0 +1,219 @@
+BattleCommand_BeatUp: ; 35461
+; beatup
+
+ call ResetDamage
+ ld a, [hBattleTurn]
+ and a
+ jp nz, .enemy_beats_up
+ ld a, [PlayerSubStatus3]
+ bit SUBSTATUS_IN_LOOP, a
+ jr nz, .next_mon
+ ld c, 20
+ call DelayFrames
+ xor a
+ ld [PlayerRolloutCount], a
+ ld [wd002], a
+ ld [wBeatUpHitAtLeastOnce], a
+ jr .got_mon
+
+.next_mon
+ ld a, [PlayerRolloutCount]
+ ld b, a
+ ld a, [PartyCount]
+ sub b
+ ld [wd002], a
+
+.got_mon
+ ld a, [wd002]
+ ld hl, PartyMonNicknames
+ call GetNick
+ ld a, MON_HP
+ call GetBeatupMonLocation
+ ld a, [hli]
+ or [hl]
+ jp z, .beatup_fail ; fainted
+ ld a, [wd002]
+ ld c, a
+ ld a, [CurBattleMon]
+ ; BUG: this can desynchronize link battles
+ ; Change "cp [hl]" to "cp c" to fix
+ cp [hl]
+ ld hl, BattleMonStatus
+ jr z, .active_mon
+ ld a, MON_STATUS
+ call GetBeatupMonLocation
+.active_mon
+ ld a, [hl]
+ and a
+ jp nz, .beatup_fail
+
+ ld a, $1
+ ld [wBeatUpHitAtLeastOnce], a
+ ld hl, BeatUpAttackText
+ call StdBattleTextBox
+ ld a, [EnemyMonSpecies]
+ ld [CurSpecies], a
+ call GetBaseData
+ ld a, [BaseDefense]
+ ld c, a
+ push bc
+ ld a, MON_SPECIES
+ call GetBeatupMonLocation
+ ld a, [hl]
+ ld [CurSpecies], a
+ call GetBaseData
+ ld a, [BaseAttack]
+ pop bc
+ ld b, a
+ push bc
+ ld a, MON_LEVEL
+ call GetBeatupMonLocation
+ ld a, [hl]
+ ld e, a
+ pop bc
+ ld a, [wPlayerMoveStructPower]
+ ld d, a
+ ret
+
+.enemy_beats_up
+ ld a, [EnemySubStatus3]
+ bit SUBSTATUS_IN_LOOP, a
+ jr nz, .not_first_enemy_beatup
+
+ xor a
+ ld [EnemyRolloutCount], a
+ ld [wd002], a
+ ld [wBeatUpHitAtLeastOnce], a
+ jr .enemy_continue
+
+.not_first_enemy_beatup
+ ld a, [EnemyRolloutCount]
+ ld b, a
+ ld a, [OTPartyCount]
+ sub b
+ ld [wd002], a
+.enemy_continue
+ ld a, [wBattleMode]
+ dec a
+ jr z, .wild
+
+ ld a, [wLinkMode]
+ and a
+ jr nz, .link_or_tower
+
+ ld a, [InBattleTowerBattle]
+ and a
+ jr nz, .link_or_tower
+
+ ld a, [wd002]
+ ld c, a
+ ld b, 0
+ ld hl, OTPartySpecies
+ add hl, bc
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ jr .got_enemy_nick
+
+.link_or_tower
+ ld a, [wd002]
+ ld hl, OTPartyMonNicknames
+ ld bc, NAME_LENGTH
+ call AddNTimes
+ ld de, StringBuffer1
+ call CopyBytes
+.got_enemy_nick
+ ld a, MON_HP
+ call GetBeatupMonLocation
+ ld a, [hli]
+ or [hl]
+ jp z, .beatup_fail
+ ld a, [wd002]
+ ld b, a
+ ld a, [CurOTMon]
+ cp b
+ ld hl, EnemyMonStatus
+ jr z, .active_enemy
+
+ ld a, MON_STATUS
+ call GetBeatupMonLocation
+.active_enemy
+ ld a, [hl]
+ and a
+ jr nz, .beatup_fail
+
+ ld a, $1
+ ld [wBeatUpHitAtLeastOnce], a
+ jr .finish_beatup
+
+.wild
+ ld a, [EnemyMonSpecies]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, BeatUpAttackText
+ call StdBattleTextBox
+ jp EnemyAttackDamage
+
+.finish_beatup
+ ld hl, BeatUpAttackText
+ call StdBattleTextBox
+ ld a, [BattleMonSpecies]
+ ld [CurSpecies], a
+ call GetBaseData
+ ld a, [BaseDefense]
+ ld c, a
+ push bc
+ ld a, MON_SPECIES
+ call GetBeatupMonLocation
+ ld a, [hl]
+ ld [CurSpecies], a
+ call GetBaseData
+ ld a, [BaseAttack]
+ pop bc
+ ld b, a
+ push bc
+ ld a, MON_LEVEL
+ call GetBeatupMonLocation
+ ld a, [hl]
+ ld e, a
+ pop bc
+ ld a, [wEnemyMoveStructPower]
+ ld d, a
+ ret
+
+; 355b0
+
+
+.beatup_fail ; 355b0
+ ld b, buildopponentrage_command
+ jp SkipToBattleCommand
+
+; 355b5
+
+
+BattleCommanda8: ; 355b5
+ ld a, [wBeatUpHitAtLeastOnce]
+ and a
+ ret nz
+
+ jp PrintButItFailed
+
+; 355bd
+
+
+GetBeatupMonLocation: ; 355bd
+ push bc
+ ld c, a
+ ld b, 0
+ ld a, [hBattleTurn]
+ and a
+ ld hl, PartyMon1Species
+ jr z, .got_species
+ ld hl, OTPartyMon1Species
+
+.got_species
+ ld a, [wd002]
+ add hl, bc
+ call GetPartyLocation
+ pop bc
+ ret
--- /dev/null
+++ b/engine/battle/move_effects/belly_drum.asm
@@ -1,0 +1,36 @@
+BattleCommand_BellyDrum: ; 37c1a
+; bellydrum
+; This command is buggy because it raises the user's attack
+; before checking that it has enough HP to use the move.
+; Swap the order of these two blocks to fix.
+ call BattleCommand_AttackUp2
+ ld a, [AttackMissed]
+ and a
+ jr nz, .failed
+
+ callfar GetHalfMaxHP
+ callfar CheckUserHasEnoughHP
+ jr nc, .failed
+
+ push bc
+ call AnimateCurrentMove
+ pop bc
+ callfar SubtractHPFromUser
+ call UpdateUserInParty
+ ld a, 5
+
+.max_attack_loop
+ push af
+ call BattleCommand_AttackUp2
+ pop af
+ dec a
+ jr nz, .max_attack_loop
+
+ ld hl, BellyDrumText
+ jp StdBattleTextBox
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+; 37c55
--- /dev/null
+++ b/engine/battle/move_effects/bide.asm
@@ -1,0 +1,105 @@
+BattleCommand_StoreEnergy: ; 36671
+; storeenergy
+
+ ld a, BATTLE_VARS_SUBSTATUS3
+ call GetBattleVar
+ bit SUBSTATUS_BIDE, a
+ ret z
+
+ ld hl, PlayerRolloutCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .check_still_storing_energy
+ ld hl, EnemyRolloutCount
+.check_still_storing_energy
+ dec [hl]
+ jr nz, .still_storing
+
+ ld a, BATTLE_VARS_SUBSTATUS3
+ call GetBattleVarAddr
+ res SUBSTATUS_BIDE, [hl]
+
+ ld hl, UnleashedEnergyText
+ call StdBattleTextBox
+
+ ld a, BATTLE_VARS_MOVE_POWER
+ call GetBattleVarAddr
+ ld a, 1
+ ld [hl], a
+ ld hl, PlayerDamageTaken + 1
+ ld de, wPlayerCharging ; player
+ ld a, [hBattleTurn]
+ and a
+ jr z, .player
+ ld hl, EnemyDamageTaken + 1
+ ld de, wEnemyCharging ; enemy
+.player
+ ld a, [hld]
+ add a
+ ld b, a
+ ld [CurDamage + 1], a
+ ld a, [hl]
+ rl a
+ ld [CurDamage], a
+ jr nc, .not_maxed
+ ld a, $ff
+ ld [CurDamage], a
+ ld [CurDamage + 1], a
+.not_maxed
+ or b
+ jr nz, .built_up_something
+ ld a, 1
+ ld [AttackMissed], a
+.built_up_something
+ xor a
+ ld [hli], a
+ ld [hl], a
+ ld [de], a
+
+ ld a, BATTLE_VARS_MOVE_ANIM
+ call GetBattleVarAddr
+ ld a, BIDE
+ ld [hl], a
+
+ ld b, unleashenergy_command
+ jp SkipToBattleCommand
+
+.still_storing
+ ld hl, StoringEnergyText
+ call StdBattleTextBox
+ jp EndMoveEffect
+
+; 366e5
+
+
+BattleCommand_UnleashEnergy: ; 366e5
+; unleashenergy
+
+ ld de, PlayerDamageTaken
+ ld bc, PlayerRolloutCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_damage
+ ld de, EnemyDamageTaken
+ ld bc, EnemyRolloutCount
+.got_damage
+ ld a, BATTLE_VARS_SUBSTATUS3
+ call GetBattleVarAddr
+ set SUBSTATUS_BIDE, [hl]
+ xor a
+ ld [de], a
+ inc de
+ ld [de], a
+ ld [wPlayerMoveStructEffect], a
+ ld [wEnemyMoveStructEffect], a
+ call BattleRandom
+ and 1
+ inc a
+ inc a
+ ld [bc], a
+ ld a, 1
+ ld [wKickCounter], a
+ call AnimateCurrentMove
+ jp EndMoveEffect
+
+; 3671a
--- /dev/null
+++ b/engine/battle/move_effects/conversion.asm
@@ -1,0 +1,98 @@
+BattleCommand_Conversion: ; 3707f
+; conversion
+
+ ld hl, BattleMonMoves
+ ld de, BattleMonType1
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_moves
+ ld hl, EnemyMonMoves
+ ld de, EnemyMonType1
+.got_moves
+ push de
+ ld c, 0
+ ld de, StringBuffer1
+.loop
+ push hl
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ pop hl
+ and a
+ jr z, .okay
+ push hl
+ push bc
+ dec a
+ ld hl, Moves + MOVE_TYPE
+ call GetMoveAttr
+ ld [de], a
+ inc de
+ pop bc
+ pop hl
+ inc c
+ ld a, c
+ cp NUM_MOVES
+ jr c, .loop
+.okay
+ ld a, $ff
+ ld [de], a
+ inc de
+ ld [de], a
+ inc de
+ ld [de], a
+ pop de
+ ld hl, StringBuffer1
+.loop2
+ ld a, [hl]
+ cp -1
+ jr z, .fail
+ cp CURSE_T
+ jr z, .next
+ ld a, [de]
+ cp [hl]
+ jr z, .next
+ inc de
+ ld a, [de]
+ dec de
+ cp [hl]
+ jr nz, .done
+.next
+ inc hl
+ jr .loop2
+
+.fail
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+.done
+.loop3
+ call BattleRandom
+ maskbits NUM_MOVES
+ ld c, a
+ ld b, 0
+ ld hl, StringBuffer1
+ add hl, bc
+ ld a, [hl]
+ cp -1
+ jr z, .loop3
+ cp CURSE_T
+ jr z, .loop3
+ ld a, [de]
+ cp [hl]
+ jr z, .loop3
+ inc de
+ ld a, [de]
+ dec de
+ cp [hl]
+ jr z, .loop3
+ ld a, [hl]
+ ld [de], a
+ inc de
+ ld [de], a
+ ld [wNamedObjectIndexBuffer], a
+ farcall GetTypeName
+ call AnimateCurrentMove
+ ld hl, TransformedTypeText
+ jp StdBattleTextBox
+
+; 3710e
--- /dev/null
+++ b/engine/battle/move_effects/conversion2.asm
@@ -1,0 +1,66 @@
+BattleCommand_Conversion2: ; 359e6
+; conversion2
+
+ ld a, [AttackMissed]
+ and a
+ jr nz, .failed
+ ld hl, BattleMonType1
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_type
+ ld hl, EnemyMonType1
+.got_type
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ jr z, .failed
+ push hl
+ dec a
+ ld hl, Moves + MOVE_TYPE
+ call GetMoveAttr
+ ld d, a
+ pop hl
+ cp CURSE_T
+ jr z, .failed
+ call AnimateCurrentMove
+ call BattleCommand_SwitchTurn
+
+.loop
+ call BattleRandom
+ and $1f
+ cp UNUSED_TYPES
+ jr c, .okay
+ cp UNUSED_TYPES_END
+ jr c, .loop
+ cp TYPES_END
+ jr nc, .loop
+.okay
+ ld [hli], a
+ ld [hld], a
+ push hl
+ ld a, BATTLE_VARS_MOVE_TYPE
+ call GetBattleVarAddr
+ push af
+ push hl
+ ld a, d
+ ld [hl], a
+ call BattleCheckTypeMatchup
+ pop hl
+ pop af
+ ld [hl], a
+ pop hl
+ ld a, [wTypeMatchup]
+ cp 10
+ jr nc, .loop
+ call BattleCommand_SwitchTurn
+
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ predef GetTypeName
+ ld hl, TransformedTypeText
+ jp StdBattleTextBox
+
+.failed
+ jp FailMove
+
+; 35a53
--- /dev/null
+++ b/engine/battle/move_effects/counter.asm
@@ -1,0 +1,60 @@
+BattleCommand_Counter: ; 35813
+; counter
+
+ ld a, 1
+ ld [AttackMissed], a
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ ret z
+
+ ld b, a
+ callfar GetMoveEffect
+ ld a, b
+ cp EFFECT_COUNTER
+ ret z
+
+ call BattleCommand_ResetTypeMatchup
+ ld a, [wTypeMatchup]
+ and a
+ ret z
+
+ call CheckOpponentWentFirst
+ ret z
+
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ dec a
+ ld de, StringBuffer1
+ call GetMoveData
+
+ ld a, [StringBuffer1 + MOVE_POWER]
+ and a
+ ret z
+
+ ld a, [StringBuffer1 + MOVE_TYPE]
+ cp SPECIAL
+ ret nc
+
+ ld hl, CurDamage
+ ld a, [hli]
+ or [hl]
+ ret z
+
+ ld a, [hl]
+ add a
+ ld [hld], a
+ ld a, [hl]
+ adc a
+ ld [hl], a
+ jr nc, .capped
+ ld a, $ff
+ ld [hli], a
+ ld [hl], a
+.capped
+
+ xor a
+ ld [AttackMissed], a
+ ret
+
+; 35864
--- /dev/null
+++ b/engine/battle/move_effects/curse.asm
@@ -1,0 +1,97 @@
+BattleCommand_Curse: ; 37588
+; curse
+
+ ld de, BattleMonType1
+ ld bc, PlayerStatLevels
+ ld a, [hBattleTurn]
+ and a
+ jr z, .go
+ ld de, EnemyMonType1
+ ld bc, EnemyStatLevels
+
+.go
+
+; Curse is different for Ghost-types.
+
+ ld a, [de]
+ cp GHOST
+ jr z, .ghost
+ inc de
+ ld a, [de]
+ cp GHOST
+ jr z, .ghost
+
+
+; If no stats can be increased, don't.
+
+; Attack
+ ld a, [bc]
+ cp MAX_STAT_LEVEL
+ jr c, .raise
+
+; Defense
+ inc bc
+ ld a, [bc]
+ cp MAX_STAT_LEVEL
+ jr nc, .cantraise
+
+.raise
+
+; Raise Attack and Defense, and lower Speed.
+
+ ld a, $1
+ ld [wKickCounter], a
+ call AnimateCurrentMove
+ ld a, SPEED
+ call LowerStat
+ call BattleCommand_SwitchTurn
+ call BattleCommand_StatDownMessage
+ call ResetMiss
+ call BattleCommand_SwitchTurn
+ call BattleCommand_AttackUp
+ call BattleCommand_StatUpMessage
+ call ResetMiss
+ call BattleCommand_DefenseUp
+ jp BattleCommand_StatUpMessage
+
+
+.ghost
+
+; Cut HP in half and put a curse on the opponent.
+
+ call CheckHiddenOpponent
+ jr nz, .failed
+
+ call CheckSubstituteOpp
+ jr nz, .failed
+
+ ld a, BATTLE_VARS_SUBSTATUS1_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_CURSE, [hl]
+ jr nz, .failed
+
+ set SUBSTATUS_CURSE, [hl]
+ call AnimateCurrentMove
+ ld hl, GetHalfMaxHP
+ call CallBattleCore
+ ld hl, SubtractHPFromUser
+ call CallBattleCore
+ call UpdateUserInParty
+ ld hl, PutACurseText
+ jp StdBattleTextBox
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+
+.cantraise
+
+; Can't raise either stat.
+
+ ld b, ABILITY + 1
+ call GetStatName
+ call AnimateFailedMove
+ ld hl, WontRiseAnymoreText
+ jp StdBattleTextBox
+; 37618
--- /dev/null
+++ b/engine/battle/move_effects/destiny_bond.asm
@@ -1,0 +1,11 @@
+BattleCommand_DestinyBond: ; 35bff
+; destinybond
+
+ ld a, BATTLE_VARS_SUBSTATUS5
+ call GetBattleVarAddr
+ set SUBSTATUS_DESTINY_BOND, [hl]
+ call AnimateCurrentMove
+ ld hl, DestinyBondEffectText
+ jp StdBattleTextBox
+
+; 35c0f
--- /dev/null
+++ b/engine/battle/move_effects/disable.asm
@@ -1,0 +1,74 @@
+BattleCommand_Disable: ; 36fed
+; disable
+
+ ld a, [AttackMissed]
+ and a
+ jr nz, .failed
+
+ ld de, EnemyDisableCount
+ ld hl, EnemyMonMoves
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_moves
+ ld de, PlayerDisableCount
+ ld hl, BattleMonMoves
+.got_moves
+
+ ld a, [de]
+ and a
+ jr nz, .failed
+
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ jr z, .failed
+ cp STRUGGLE
+ jr z, .failed
+
+ ld b, a
+ ld c, $ff
+.loop
+ inc c
+ ld a, [hli]
+ cp b
+ jr nz, .loop
+
+ ld a, [hBattleTurn]
+ and a
+ ld hl, EnemyMonPP
+ jr z, .got_pp
+ ld hl, BattleMonPP
+.got_pp
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ and a
+ jr z, .failed
+.loop2
+ call BattleRandom
+ and 7
+ jr z, .loop2
+ inc a
+ inc c
+ swap c
+ add c
+ ld [de], a
+ call AnimateCurrentMove
+ ld hl, DisabledMove
+ ld a, [hBattleTurn]
+ and a
+ jr nz, .got_disabled_move_pointer
+ inc hl
+.got_disabled_move_pointer
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ ld [hl], a
+ ld [wNamedObjectIndexBuffer], a
+ call GetMoveName
+ ld hl, WasDisabledText
+ jp StdBattleTextBox
+
+.failed
+ jp FailMove
+
+; 3705c
--- /dev/null
+++ b/engine/battle/move_effects/encore.asm
@@ -1,0 +1,122 @@
+BattleCommand_Encore: ; 35864
+; encore
+
+ ld hl, EnemyMonMoves
+ ld de, EnemyEncoreCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld hl, BattleMonMoves
+ ld de, PlayerEncoreCount
+.ok
+ ld a, BATTLE_VARS_LAST_MOVE_OPP
+ call GetBattleVar
+ and a
+ jp z, .failed
+ cp STRUGGLE
+ jp z, .failed
+ cp ENCORE
+ jp z, .failed
+ cp MIRROR_MOVE
+ jp z, .failed
+ ld b, a
+
+.got_move
+ ld a, [hli]
+ cp b
+ jr nz, .got_move
+
+ ld bc, BattleMonPP - BattleMonMoves - 1
+ add hl, bc
+ ld a, [hl]
+ and PP_MASK
+ jp z, .failed
+ ld a, [AttackMissed]
+ and a
+ jp nz, .failed
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_ENCORED, [hl]
+ jp nz, .failed
+ set SUBSTATUS_ENCORED, [hl]
+ call BattleRandom
+ and $3
+ inc a
+ inc a
+ inc a
+ ld [de], a
+ call CheckOpponentWentFirst
+ jr nz, .finish_move
+ ld a, [hBattleTurn]
+ and a
+ jr z, .force_last_enemy_move
+
+ push hl
+ ld a, [LastPlayerMove]
+ ld b, a
+ ld c, 0
+ ld hl, BattleMonMoves
+.find_player_move
+ ld a, [hli]
+ cp b
+ jr z, .got_player_move
+ inc c
+ ld a, c
+ cp NUM_MOVES
+ jr c, .find_player_move
+ pop hl
+ res SUBSTATUS_ENCORED, [hl]
+ xor a
+ ld [de], a
+ jr .failed
+
+.got_player_move
+ pop hl
+ ld a, c
+ ld [CurMoveNum], a
+ ld a, b
+ ld [CurPlayerMove], a
+ dec a
+ ld de, wPlayerMoveStruct
+ call GetMoveData
+ jr .finish_move
+
+.force_last_enemy_move
+ push hl
+ ld a, [LastEnemyMove]
+ ld b, a
+ ld c, 0
+ ld hl, EnemyMonMoves
+.find_enemy_move
+ ld a, [hli]
+ cp b
+ jr z, .got_enemy_move
+ inc c
+ ld a, c
+ cp NUM_MOVES
+ jr c, .find_enemy_move
+ pop hl
+ res SUBSTATUS_ENCORED, [hl]
+ xor a
+ ld [de], a
+ jr .failed
+
+.got_enemy_move
+ pop hl
+ ld a, c
+ ld [CurEnemyMoveNum], a
+ ld a, b
+ ld [CurEnemyMove], a
+ dec a
+ ld de, wEnemyMoveStruct
+ call GetMoveData
+
+.finish_move
+ call AnimateCurrentMove
+ ld hl, GotAnEncoreText
+ jp StdBattleTextBox
+
+.failed
+ jp PrintDidntAffect2
+
+; 35926
--- /dev/null
+++ b/engine/battle/move_effects/endure.asm
@@ -1,0 +1,17 @@
+BattleCommand_Endure: ; 3766f
+; endure
+
+; Endure shares code with Protect. See protect.asm.
+
+ call ProtectChance
+ ret c
+
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ set SUBSTATUS_ENDURE, [hl]
+
+ call AnimateCurrentMove
+
+ ld hl, BracedItselfText
+ jp StdBattleTextBox
+; 37683
--- /dev/null
+++ b/engine/battle/move_effects/false_swipe.asm
@@ -1,0 +1,44 @@
+BattleCommand_FalseSwipe: ; 35c94
+; falseswipe
+
+ ld hl, EnemyMonHP
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_hp
+ ld hl, BattleMonHP
+.got_hp
+ ld de, CurDamage
+ ld c, 2
+ push hl
+ push de
+ call StringCmp
+ pop de
+ pop hl
+ jr c, .done
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ dec a
+ ld [de], a
+ inc a
+ jr nz, .okay
+ dec de
+ ld a, [de]
+ dec a
+ ld [de], a
+.okay
+ ld a, [CriticalHit]
+ cp 2
+ jr nz, .carry
+ xor a
+ ld [CriticalHit], a
+.carry
+ scf
+ ret
+
+.done
+ and a
+ ret
+
+; 35cc9
--- /dev/null
+++ b/engine/battle/move_effects/focus_energy.asm
@@ -1,0 +1,17 @@
+BattleCommand_FocusEnergy: ; 36c98
+; focusenergy
+
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ bit SUBSTATUS_FOCUS_ENERGY, [hl]
+ jr nz, .already_pumped
+ set SUBSTATUS_FOCUS_ENERGY, [hl]
+ call AnimateCurrentMove
+ ld hl, GettingPumpedText
+ jp StdBattleTextBox
+
+.already_pumped
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+; 36cb2
--- /dev/null
+++ b/engine/battle/move_effects/foresight.asm
@@ -1,0 +1,23 @@
+BattleCommand_Foresight: ; 376a0
+; foresight
+
+ ld a, [AttackMissed]
+ and a
+ jr nz, .failed
+
+ call CheckHiddenOpponent
+ jr nz, .failed
+
+ ld a, BATTLE_VARS_SUBSTATUS1_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_IDENTIFIED, [hl]
+ jr nz, .failed
+
+ set SUBSTATUS_IDENTIFIED, [hl]
+ call AnimateCurrentMove
+ ld hl, IdentifiedText
+ jp StdBattleTextBox
+
+.failed
+ jp FailMove
+; 376c2
--- /dev/null
+++ b/engine/battle/move_effects/frustration.asm
@@ -1,0 +1,29 @@
+BattleCommand_FrustrationPower: ; 3790e
+; frustrationpower
+
+ push bc
+ ld hl, BattleMonHappiness
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_happiness
+ ld hl, EnemyMonHappiness
+.got_happiness
+ ld a, $ff
+ sub [hl]
+ ld [hMultiplicand + 2], a
+ xor a
+ ld [hMultiplicand + 0], a
+ ld [hMultiplicand + 1], a
+ ld a, 10
+ ld [hMultiplier], a
+ call Multiply
+ ld a, 25
+ ld [hDivisor], a
+ ld b, 4
+ call Divide
+ ld a, [hQuotient + 2]
+ ld d, a
+ pop bc
+ ret
+
+; 37939
--- /dev/null
+++ b/engine/battle/move_effects/fury_cutter.asm
@@ -1,0 +1,61 @@
+BattleCommand_FuryCutter: ; 37792
+; furycutter
+
+ ld hl, PlayerFuryCutterCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .go
+ ld hl, EnemyFuryCutterCount
+
+.go
+ ld a, [AttackMissed]
+ and a
+ jp nz, ResetFuryCutterCount
+
+ inc [hl]
+
+; Damage capped at 5 turns' worth (16x).
+ ld a, [hl]
+ ld b, a
+ cp 6
+ jr c, .checkdouble
+ ld b, 5
+
+.checkdouble
+ dec b
+ ret z
+
+; Double the damage
+ ld hl, CurDamage + 1
+ sla [hl]
+ dec hl
+ rl [hl]
+ jr nc, .checkdouble
+
+; No overflow
+ ld a, $ff
+ ld [hli], a
+ ld [hl], a
+ ret
+
+; 377be
+
+
+ResetFuryCutterCount: ; 377be
+
+ push hl
+
+ ld hl, PlayerFuryCutterCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .reset
+ ld hl, EnemyFuryCutterCount
+
+.reset
+ xor a
+ ld [hl], a
+
+ pop hl
+ ret
+
+; 377ce
--- /dev/null
+++ b/engine/battle/move_effects/future_sight.asm
@@ -1,0 +1,85 @@
+BattleCommand_CheckFutureSight: ; 37d0d
+; checkfuturesight
+
+ ld hl, wPlayerFutureSightCount
+ ld de, wPlayerFutureSightDamage
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld hl, wEnemyFutureSightCount
+ ld de, wEnemyFutureSightDamage
+.ok
+
+ ld a, [hl]
+ and a
+ ret z
+ cp 1
+ ret nz
+
+ ld [hl], 0
+ ld a, [de]
+ inc de
+ ld [CurDamage], a
+ ld a, [de]
+ ld [CurDamage + 1], a
+ ld b, futuresight_command
+ jp SkipToBattleCommand
+
+; 37d34
+
+BattleCommand_FutureSight: ; 37d34
+; futuresight
+
+ call CheckUserIsCharging
+ jr nz, .AlreadyChargingFutureSight
+ ld a, BATTLE_VARS_MOVE_ANIM
+ call GetBattleVar
+ ld b, a
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE
+ call GetBattleVarAddr
+ ld [hl], b
+ ld a, BATTLE_VARS_LAST_MOVE
+ call GetBattleVarAddr
+ ld [hl], b
+.AlreadyChargingFutureSight:
+ ld hl, wPlayerFutureSightCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .GotFutureSightCount
+ ld hl, wEnemyFutureSightCount
+.GotFutureSightCount:
+ ld a, [hl]
+ and a
+ jr nz, .failed
+ ld a, 4
+ ld [hl], a
+ call BattleCommand_LowerSub
+ call BattleCommand_MoveDelay
+ ld hl, ForesawAttackText
+ call StdBattleTextBox
+ call BattleCommand_RaiseSub
+ ld de, wPlayerFutureSightDamage
+ ld a, [hBattleTurn]
+ and a
+ jr z, .StoreDamage
+ ld de, wEnemyFutureSightDamage
+.StoreDamage:
+ ld hl, CurDamage
+ ld a, [hl]
+ ld [de], a
+ ld [hl], 0
+ inc hl
+ inc de
+ ld a, [hl]
+ ld [de], a
+ ld [hl], 0
+ jp EndMoveEffect
+
+.failed
+ pop bc
+ call ResetDamage
+ call AnimateFailedMove
+ call PrintButItFailed
+ jp EndMoveEffect
+
+; 37d94
--- /dev/null
+++ b/engine/battle/move_effects/heal_bell.asm
@@ -1,0 +1,36 @@
+BattleCommand_HealBell: ; 35cc9
+; healbell
+
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ res SUBSTATUS_NIGHTMARE, [hl]
+ ld de, PartyMon1Status
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_status
+ ld de, OTPartyMon1Status
+.got_status
+ ld a, BATTLE_VARS_STATUS
+ call GetBattleVarAddr
+ xor a
+ ld [hl], a
+ ld h, d
+ ld l, e
+ ld bc, PARTYMON_STRUCT_LENGTH
+ ld d, PARTY_LENGTH
+.loop
+ ld [hl], a
+ add hl, bc
+ dec d
+ jr nz, .loop
+ call AnimateCurrentMove
+
+ ld hl, BellChimedText
+ call StdBattleTextBox
+
+ ld a, [hBattleTurn]
+ and a
+ jp z, CalcPlayerStats
+ jp CalcEnemyStats
+
+; 35d00
--- /dev/null
+++ b/engine/battle/move_effects/hidden_power.asm
@@ -1,0 +1,10 @@
+BattleCommand_HiddenPower: ; 37be8
+; hiddenpower
+
+ ld a, [AttackMissed]
+ and a
+ ret nz
+ farcall HiddenPowerDamage
+ ret
+
+; 37bf4
--- /dev/null
+++ b/engine/battle/move_effects/leech_seed.asm
@@ -1,0 +1,42 @@
+BattleCommand_LeechSeed: ; 36f9d
+; leechseed
+ ld a, [AttackMissed]
+ and a
+ jr nz, .evaded
+ call CheckSubstituteOpp
+ jr nz, .evaded
+
+ ld de, EnemyMonType1
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld de, BattleMonType1
+.ok
+
+ ld a, [de]
+ cp GRASS
+ jr z, .grass
+ inc de
+ ld a, [de]
+ cp GRASS
+ jr z, .grass
+
+ ld a, BATTLE_VARS_SUBSTATUS4_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_LEECH_SEED, [hl]
+ jr nz, .evaded
+ set SUBSTATUS_LEECH_SEED, [hl]
+ call AnimateCurrentMove
+ ld hl, WasSeededText
+ jp StdBattleTextBox
+
+.grass
+ call AnimateFailedMove
+ jp PrintDoesntAffect
+
+.evaded
+ call AnimateFailedMove
+ ld hl, EvadedText
+ jp StdBattleTextBox
+
+; 36fe1
--- /dev/null
+++ b/engine/battle/move_effects/lock_on.asm
@@ -1,0 +1,23 @@
+BattleCommand_LockOn: ; 35a53
+; lockon
+
+ call CheckSubstituteOpp
+ jr nz, .fail
+
+ ld a, [AttackMissed]
+ and a
+ jr nz, .fail
+
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVarAddr
+ set SUBSTATUS_LOCK_ON, [hl]
+ call AnimateCurrentMove
+
+ ld hl, TookAimText
+ jp StdBattleTextBox
+
+.fail
+ call AnimateFailedMove
+ jp PrintDidntAffect
+
+; 35a74
--- /dev/null
+++ b/engine/battle/move_effects/magnitude.asm
@@ -1,0 +1,29 @@
+BattleCommand_GetMagnitude: ; 37991
+; getmagnitude
+
+ push bc
+ call BattleRandom
+ ld b, a
+ ld hl, MagnitudePower
+.loop
+ ld a, [hli]
+ cp b
+ jr nc, .ok
+ inc hl
+ inc hl
+ jr .loop
+
+.ok
+ ld d, [hl]
+ push de
+ inc hl
+ ld a, [hl]
+ ld [wTypeMatchup], a
+ call BattleCommand_MoveDelay
+ ld hl, MagnitudeText
+ call StdBattleTextBox
+ pop de
+ pop bc
+ ret
+
+INCLUDE "data/moves/magnitude_power.asm"
--- /dev/null
+++ b/engine/battle/move_effects/metronome.asm
@@ -1,0 +1,46 @@
+BattleCommand_Metronome: ; 37418
+; metronome
+
+ call ClearLastMove
+ call CheckUserIsCharging
+ jr nz, .asm_3742b
+
+ ld a, [wKickCounter]
+ push af
+ call BattleCommand_LowerSub
+ pop af
+ ld [wKickCounter], a
+
+.asm_3742b
+ call LoadMoveAnim
+
+.GetMove:
+ call BattleRandom
+
+; No invalid moves.
+ cp NUM_ATTACKS + 1
+ jr nc, .GetMove
+
+; None of the moves in MetronomeExcepts.
+ push af
+ ld de, 1
+ ld hl, MetronomeExcepts
+ call IsInArray
+ pop bc
+ jr c, .GetMove
+
+; No moves the user already has.
+ ld a, b
+ call CheckUserMove
+ jr z, .GetMove
+
+
+ ld a, BATTLE_VARS_MOVE
+ call GetBattleVarAddr
+ ld [hl], b
+ call UpdateMoveData
+ jp ResetTurn
+; 37454
+
+
+INCLUDE "data/battle/metronome_exception_moves.asm"
--- /dev/null
+++ b/engine/battle/move_effects/mimic.asm
@@ -1,0 +1,52 @@
+BattleCommand_Mimic: ; 36f46
+; mimic
+
+ call ClearLastMove
+ call BattleCommand_MoveDelay
+ ld a, [AttackMissed]
+ and a
+ jr nz, .fail
+ ld hl, BattleMonMoves
+ ld a, [hBattleTurn]
+ and a
+ jr z, .player_turn
+ ld hl, EnemyMonMoves
+.player_turn
+ call CheckHiddenOpponent
+ jr nz, .fail
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ jr z, .fail
+ cp STRUGGLE
+ jr z, .fail
+ ld b, a
+ ld c, NUM_MOVES
+.check_already_knows_move
+ ld a, [hli]
+ cp b
+ jr z, .fail
+ dec c
+ jr nz, .check_already_knows_move
+ dec hl
+.find_mimic
+ ld a, [hld]
+ cp MIMIC
+ jr nz, .find_mimic
+ inc hl
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ ld [hl], a
+ ld [wNamedObjectIndexBuffer], a
+ ld bc, BattleMonPP - BattleMonMoves
+ add hl, bc
+ ld [hl], 5
+ call GetMoveName
+ call AnimateCurrentMove
+ ld hl, LearnedMoveText
+ jp StdBattleTextBox
+
+.fail
+ jp FailMimic
+
+; 36f9d
--- /dev/null
+++ b/engine/battle/move_effects/mirror_coat.asm
@@ -1,0 +1,61 @@
+BattleCommand_MirrorCoat: ; 37c95
+; mirrorcoat
+
+ ld a, 1
+ ld [AttackMissed], a
+
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ ret z
+
+ ld b, a
+ callfar GetMoveEffect
+ ld a, b
+ cp EFFECT_MIRROR_COAT
+ ret z
+
+ call BattleCommand_ResetTypeMatchup
+ ld a, [wTypeMatchup]
+ and a
+ ret z
+
+ call CheckOpponentWentFirst
+ ret z
+
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ dec a
+ ld de, StringBuffer1
+ call GetMoveData
+
+ ld a, [StringBuffer1 + 2]
+ and a
+ ret z
+
+ ld a, [StringBuffer1 + 3]
+ cp SPECIAL
+ ret c
+
+ ld hl, CurDamage
+ ld a, [hli]
+ or [hl]
+ ret z
+
+ ld a, [hl]
+ add a
+ ld [hld], a
+ ld a, [hl]
+ adc a
+ ld [hl], a
+ jr nc, .capped
+ ld a, $ff
+ ld [hli], a
+ ld [hl], a
+.capped
+
+ xor a
+ ld [AttackMissed], a
+ ret
+
+; 37ce6
--- /dev/null
+++ b/engine/battle/move_effects/mirror_move.asm
@@ -1,0 +1,52 @@
+BattleCommand_MirrorMove: ; 373c9
+; mirrormove
+
+ call ClearLastMove
+
+ ld a, BATTLE_VARS_MOVE
+ call GetBattleVarAddr
+
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ jr z, .failed
+
+ call CheckUserMove
+ jr nz, .use
+
+.failed
+ call AnimateFailedMove
+
+ ld hl, MirrorMoveFailedText
+ call StdBattleTextBox
+ jp EndMoveEffect
+
+.use
+ ld a, b
+ ld [hl], a
+ ld [wd265], a
+
+ push af
+ ld a, BATTLE_VARS_MOVE_ANIM
+ call GetBattleVarAddr
+ ld d, h
+ ld e, l
+ pop af
+
+ dec a
+ call GetMoveData
+ call GetMoveName
+ call CopyName1
+ call CheckUserIsCharging
+ jr nz, .done
+
+ ld a, [wKickCounter]
+ push af
+ call BattleCommand_LowerSub
+ pop af
+ ld [wKickCounter], a
+
+.done
+ call BattleCommand_MoveDelay
+ jp ResetTurn
+; 37418
--- /dev/null
+++ b/engine/battle/move_effects/mist.asm
@@ -1,0 +1,17 @@
+BattleCommand_Mist: ; 36c7e
+; mist
+
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ bit SUBSTATUS_MIST, [hl]
+ jr nz, .already_mist
+ set SUBSTATUS_MIST, [hl]
+ call AnimateCurrentMove
+ ld hl, MistText
+ jp StdBattleTextBox
+
+.already_mist
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+; 36c98
--- /dev/null
+++ b/engine/battle/move_effects/nightmare.asm
@@ -1,0 +1,38 @@
+BattleCommand_Nightmare: ; 37536
+; nightmare
+
+; Can't hit an absent opponent.
+
+ call CheckHiddenOpponent
+ jr nz, .failed
+
+; Can't hit a substitute.
+
+ call CheckSubstituteOpp
+ jr nz, .failed
+
+; Only works on a sleeping opponent.
+
+ ld a, BATTLE_VARS_STATUS_OPP
+ call GetBattleVarAddr
+ and SLP
+ jr z, .failed
+
+; Bail if the opponent is already having a nightmare.
+
+ ld a, BATTLE_VARS_SUBSTATUS1_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_NIGHTMARE, [hl]
+ jr nz, .failed
+
+; Otherwise give the opponent a nightmare.
+
+ set SUBSTATUS_NIGHTMARE, [hl]
+ call AnimateCurrentMove
+ ld hl, StartedNightmareText
+ jp StdBattleTextBox
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+; 37563
--- /dev/null
+++ b/engine/battle/move_effects/pain_split.asm
@@ -1,0 +1,97 @@
+BattleCommand_PainSplit: ; 35926
+; painsplit
+
+ ld a, [AttackMissed]
+ and a
+ jp nz, .ButItFailed
+ call CheckSubstituteOpp
+ jp nz, .ButItFailed
+ call AnimateCurrentMove
+ ld hl, BattleMonMaxHP + 1
+ ld de, EnemyMonMaxHP + 1
+ call .PlayerShareHP
+ ld a, $1
+ ld [wWhichHPBar], a
+ hlcoord 10, 9
+ predef AnimateHPBar
+ ld hl, EnemyMonHP
+ ld a, [hli]
+ ld [Buffer4], a
+ ld a, [hli]
+ ld [Buffer3], a
+ ld a, [hli]
+ ld [Buffer2], a
+ ld a, [hl]
+ ld [Buffer1], a
+ call .EnemyShareHP
+ xor a
+ ld [wWhichHPBar], a
+ call ResetDamage
+ hlcoord 2, 2
+ predef AnimateHPBar
+ farcall _UpdateBattleHUDs
+
+ ld hl, SharedPainText
+ jp StdBattleTextBox
+
+.PlayerShareHP:
+ ld a, [hld]
+ ld [Buffer1], a
+ ld a, [hld]
+ ld [Buffer2], a
+ ld a, [hld]
+ ld b, a
+ ld [Buffer3], a
+ ld a, [hl]
+ ld [Buffer4], a
+ dec de
+ dec de
+ ld a, [de]
+ dec de
+ add b
+ ld [CurDamage + 1], a
+ ld b, [hl]
+ ld a, [de]
+ adc b
+ srl a
+ ld [CurDamage], a
+ ld a, [CurDamage + 1]
+ rr a
+ ld [CurDamage + 1], a
+ inc hl
+ inc hl
+ inc hl
+ inc de
+ inc de
+ inc de
+
+.EnemyShareHP: ; 359ac
+ ld c, [hl]
+ dec hl
+ ld a, [CurDamage + 1]
+ sub c
+ ld b, [hl]
+ dec hl
+ ld a, [CurDamage]
+ sbc b
+ jr nc, .skip
+
+ ld a, [CurDamage]
+ ld b, a
+ ld a, [CurDamage + 1]
+ ld c, a
+.skip
+ ld a, c
+ ld [hld], a
+ ld [Buffer5], a
+ ld a, b
+ ld [hli], a
+ ld [Buffer6], a
+ ret
+
+; 359cd
+
+.ButItFailed:
+ jp PrintDidntAffect2
+
+; 359d0
--- /dev/null
+++ b/engine/battle/move_effects/pay_day.asm
@@ -1,0 +1,28 @@
+BattleCommand_PayDay: ; 3705c
+; payday
+
+ xor a
+ ld hl, StringBuffer1
+ ld [hli], a
+
+ ld a, [hBattleTurn]
+ and a
+ ld a, [BattleMonLevel]
+ jr z, .ok
+ ld a, [EnemyMonLevel]
+.ok
+
+ add a
+ ld hl, wPayDayMoney + 2
+ add [hl]
+ ld [hld], a
+ jr nc, .done
+ inc [hl]
+ dec hl
+ jr nz, .done
+ inc [hl]
+.done
+ ld hl, CoinsScatteredText
+ jp StdBattleTextBox
+
+; 3707f
--- /dev/null
+++ b/engine/battle/move_effects/perish_song.asm
@@ -1,0 +1,40 @@
+BattleCommand_PerishSong: ; 376c2
+; perishsong
+
+
+ ld hl, PlayerSubStatus1
+ ld de, EnemySubStatus1
+ bit SUBSTATUS_PERISH, [hl]
+ jr z, .ok
+
+ ld a, [de]
+ bit SUBSTATUS_PERISH, a
+ jr nz, .failed
+
+.ok
+ bit SUBSTATUS_PERISH, [hl]
+ jr nz, .enemy
+
+ set SUBSTATUS_PERISH, [hl]
+ ld a, 4
+ ld [PlayerPerishCount], a
+
+.enemy
+ ld a, [de]
+ bit SUBSTATUS_PERISH, a
+ jr nz, .done
+
+ set SUBSTATUS_PERISH, a
+ ld [de], a
+ ld a, 4
+ ld [EnemyPerishCount], a
+
+.done
+ call AnimateCurrentMove
+ ld hl, StartPerishText
+ jp StdBattleTextBox
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+; 376f8
--- /dev/null
+++ b/engine/battle/move_effects/present.asm
@@ -1,0 +1,88 @@
+BattleCommand_Present: ; 37874
+; present
+
+ ld a, [wLinkMode]
+ cp LINK_COLOSSEUM
+ jr z, .colosseum_skippush
+ push bc
+ push de
+.colosseum_skippush
+
+ call BattleCommand_Stab
+
+ ld a, [wLinkMode]
+ cp LINK_COLOSSEUM
+ jr z, .colosseum_skippop
+ pop de
+ pop bc
+.colosseum_skippop
+
+ ld a, [wTypeMatchup]
+ and a
+ jp z, AnimateFailedMove
+ ld a, [AttackMissed]
+ and a
+ jp nz, AnimateFailedMove
+
+ push bc
+ call BattleRandom
+ ld b, a
+ ld hl, PresentPower
+ ld c, 0
+.next
+ ld a, [hli]
+ cp -1
+ jr z, .heal_effect ; 378a4 $11
+ cp b
+ jr nc, .got_power ; 378a7 $4
+ inc c
+ inc hl
+ jr .next ; 378ab $f4
+
+.got_power
+ ld a, c
+ ld [wPresentPower], a
+ call AnimateCurrentMoveEitherSide
+ ld d, [hl]
+ pop bc
+ ret
+
+.heal_effect
+ pop bc
+ ld a, 3
+ ld [wPresentPower], a
+ call AnimateCurrentMove
+ call BattleCommand_SwitchTurn
+ ld hl, AICheckPlayerMaxHP
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_hp_fn_pointer ; 378c9 $3
+ ld hl, AICheckEnemyMaxHP
+.got_hp_fn_pointer
+ ld a, BANK(AICheckPlayerMaxHP)
+ rst FarCall
+ jr c, .already_fully_healed ; 378d1 $20
+
+ ld hl, GetQuarterMaxHP
+ call CallBattleCore
+ call BattleCommand_SwitchTurn
+ ld hl, RestoreHP
+ call CallBattleCore
+ call BattleCommand_SwitchTurn
+ ld hl, RegainedHealthText
+ call StdBattleTextBox
+ call BattleCommand_SwitchTurn
+ call UpdateOpponentInParty
+ jr .do_animation ; 378f1 $11
+
+.already_fully_healed
+ call BattleCommand_SwitchTurn
+ call _CheckBattleScene
+ jr nc, .do_animation ; 378f9 $9
+ call AnimateFailedMove
+ ld hl, RefusedGiftText
+ call StdBattleTextBox
+.do_animation
+ jp EndMoveEffect
+
+INCLUDE "data/moves/present_power.asm"
--- /dev/null
+++ b/engine/battle/move_effects/protect.asm
@@ -1,0 +1,80 @@
+BattleCommand_Protect: ; 37618
+; protect
+ call ProtectChance
+ ret c
+
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ set SUBSTATUS_PROTECT, [hl]
+
+ call AnimateCurrentMove
+
+ ld hl, ProtectedItselfText
+ jp StdBattleTextBox
+; 3762c
+
+
+ProtectChance: ; 3762c
+
+ ld de, PlayerProtectCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .asm_37637
+ ld de, EnemyProtectCount
+.asm_37637
+
+ call CheckOpponentWentFirst
+ jr nz, .failed
+
+; Can't have a substitute.
+
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVar
+ bit SUBSTATUS_SUBSTITUTE, a
+ jr nz, .failed
+
+; Halve the chance of a successful Protect for each consecutive use.
+
+ ld b, $ff
+ ld a, [de]
+ ld c, a
+.loop
+ ld a, c
+ and a
+ jr z, .done
+ dec c
+
+ srl b
+ ld a, b
+ and a
+ jr nz, .loop
+ jr .failed
+.done
+
+.rand
+ call BattleRandom
+ and a
+ jr z, .rand
+
+ dec a
+ cp b
+ jr nc, .failed
+
+; Another consecutive Protect use.
+
+ ld a, [de]
+ inc a
+ ld [de], a
+
+ and a
+ ret
+
+
+.failed
+ xor a
+ ld [de], a
+ call AnimateFailedMove
+ call PrintButItFailed
+ scf
+ ret
+; 3766f
--- /dev/null
+++ b/engine/battle/move_effects/psych_up.asm
@@ -1,0 +1,51 @@
+BattleCommand_PsychUp: ; 37c55
+; psychup
+
+ ld hl, EnemyStatLevels
+ ld de, PlayerStatLevels
+ ld a, [hBattleTurn]
+ and a
+ jr z, .pointers_correct
+; It's the enemy's turn, so swap the pointers.
+ push hl
+ ld h, d
+ ld l, e
+ pop de
+.pointers_correct
+ push hl
+ ld b, NUM_LEVEL_STATS
+; If any of the enemy's stats is modified from its base level,
+; the move succeeds. Otherwise, it fails.
+.loop
+ ld a, [hli]
+ cp BASE_STAT_LEVEL
+ jr nz, .break
+ dec b
+ jr nz, .loop
+ pop hl
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+.break
+ pop hl
+ ld b, NUM_LEVEL_STATS
+.loop2
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .loop2
+ ld a, [hBattleTurn]
+ and a
+ jr nz, .calc_enemy_stats
+ call CalcPlayerStats
+ jr .merge
+
+.calc_enemy_stats
+ call CalcEnemyStats
+.merge
+ call AnimateCurrentMove
+ ld hl, CopiedStatsText
+ jp StdBattleTextBox
+
+; 37c95
--- /dev/null
+++ b/engine/battle/move_effects/pursuit.asm
@@ -1,0 +1,26 @@
+BattleCommand_Pursuit: ; 37b1d
+; pursuit
+; Double damage if the opponent is switching.
+
+ ld hl, wEnemyIsSwitching
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld hl, wPlayerIsSwitching
+.ok
+ ld a, [hl]
+ and a
+ ret z
+
+ ld hl, CurDamage + 1
+ sla [hl]
+ dec hl
+ rl [hl]
+ ret nc
+
+ ld a, $ff
+ ld [hli], a
+ ld [hl], a
+ ret
+
+; 37b39
--- /dev/null
+++ b/engine/battle/move_effects/rage.asm
@@ -1,0 +1,8 @@
+BattleCommand_Rage: ; 36f1d
+; rage
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ set SUBSTATUS_RAGE, [hl]
+ ret
+
+; 36f25
--- /dev/null
+++ b/engine/battle/move_effects/rain_dance.asm
@@ -1,0 +1,11 @@
+BattleCommand_StartRain: ; 37bf4
+; startrain
+ ld a, WEATHER_RAIN
+ ld [Weather], a
+ ld a, 5
+ ld [WeatherCount], a
+ call AnimateCurrentMove
+ ld hl, DownpourText
+ jp StdBattleTextBox
+
+; 37c07
--- /dev/null
+++ b/engine/battle/move_effects/rapid_spin.asm
@@ -1,0 +1,38 @@
+BattleCommand_ClearHazards: ; 37b39
+; clearhazards
+
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ bit SUBSTATUS_LEECH_SEED, [hl]
+ jr z, .not_leeched
+ res SUBSTATUS_LEECH_SEED, [hl]
+ ld hl, ShedLeechSeedText
+ call StdBattleTextBox
+.not_leeched
+
+ ld hl, PlayerScreens
+ ld de, wPlayerWrapCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_screens_wrap
+ ld hl, EnemyScreens
+ ld de, wEnemyWrapCount
+.got_screens_wrap
+ bit SCREENS_SPIKES, [hl]
+ jr z, .no_spikes
+ res SCREENS_SPIKES, [hl]
+ ld hl, BlewSpikesText
+ push de
+ call StdBattleTextBox
+ pop de
+.no_spikes
+
+ ld a, [de]
+ and a
+ ret z
+ xor a
+ ld [de], a
+ ld hl, ReleasedByText
+ jp StdBattleTextBox
+
+; 37b74
--- /dev/null
+++ b/engine/battle/move_effects/return.asm
@@ -1,0 +1,27 @@
+BattleCommand_HappinessPower: ; 3784b
+; happinesspower
+ push bc
+ ld hl, BattleMonHappiness
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld hl, EnemyMonHappiness
+.ok
+ xor a
+ ld [hMultiplicand + 0], a
+ ld [hMultiplicand + 1], a
+ ld a, [hl]
+ ld [hMultiplicand + 2], a
+ ld a, 10
+ ld [hMultiplier], a
+ call Multiply
+ ld a, 25
+ ld [hDivisor], a
+ ld b, 4
+ call Divide
+ ld a, [hQuotient + 2]
+ ld d, a
+ pop bc
+ ret
+
+; 37874
--- /dev/null
+++ b/engine/battle/move_effects/rollout.asm
@@ -1,0 +1,99 @@
+MAX_ROLLOUT_COUNT EQU 5
+
+
+BattleCommand_CheckCurl: ; 37718
+; checkcurl
+
+ ld de, PlayerRolloutCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld de, EnemyRolloutCount
+.ok
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVar
+ bit SUBSTATUS_ROLLOUT, a
+ jr z, .reset
+
+ ld b, $4 ; doturn
+ jp SkipToBattleCommand
+
+.reset
+ xor a
+ ld [de], a
+ ret
+; 37734
+
+
+BattleCommand_RolloutPower: ; 37734
+; rolloutpower
+
+ ld a, BATTLE_VARS_STATUS
+ call GetBattleVar
+ and SLP
+ ret nz
+
+ ld hl, PlayerRolloutCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_rollout_count
+ ld hl, EnemyRolloutCount
+
+.got_rollout_count
+ ld a, [hl]
+ and a
+ jr nz, .skip_set_rampage
+ ld a, 1
+ ld [wSomeoneIsRampaging], a
+
+.skip_set_rampage
+ ld a, [AttackMissed]
+ and a
+ jr z, .hit
+
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ res 6, [hl]
+ ret
+
+.hit
+ inc [hl]
+ ld a, [hl]
+ ld b, a
+ cp MAX_ROLLOUT_COUNT
+ jr c, .not_done_with_rollout
+
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ res SUBSTATUS_ROLLOUT, [hl]
+ jr .done_with_substatus_flag
+
+.not_done_with_rollout
+ ld a, BATTLE_VARS_SUBSTATUS1
+ call GetBattleVarAddr
+ set SUBSTATUS_ROLLOUT, [hl]
+
+.done_with_substatus_flag
+ ld a, BATTLE_VARS_SUBSTATUS2
+ call GetBattleVar
+ bit SUBSTATUS_CURLED, a
+ jr z, .not_curled
+ inc b
+.not_curled
+.loop
+ dec b
+ jr z, .done_damage
+
+ ld hl, CurDamage + 1
+ sla [hl]
+ dec hl
+ rl [hl]
+ jr nc, .loop
+
+ ld a, $ff
+ ld [hli], a
+ ld [hl], a
+
+.done_damage
+ ret
+; 37791
--- /dev/null
+++ b/engine/battle/move_effects/safeguard.asm
@@ -1,0 +1,25 @@
+BattleCommand_Safeguard: ; 37939
+; safeguard
+
+ ld hl, PlayerScreens
+ ld de, PlayerSafeguardCount
+ ld a, [hBattleTurn]
+ and a
+ jr z, .ok
+ ld hl, EnemyScreens
+ ld de, EnemySafeguardCount
+.ok
+ bit SCREENS_SAFEGUARD, [hl]
+ jr nz, .failed
+ set SCREENS_SAFEGUARD, [hl]
+ ld a, 5
+ ld [de], a
+ call AnimateCurrentMove
+ ld hl, CoveredByVeilText
+ jp StdBattleTextBox
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+; 37962
--- /dev/null
+++ b/engine/battle/move_effects/sandstorm.asm
@@ -1,0 +1,19 @@
+BattleCommand_StartSandstorm: ; 376f8
+; startsandstorm
+
+ ld a, [Weather]
+ cp WEATHER_SANDSTORM
+ jr z, .failed
+
+ ld a, WEATHER_SANDSTORM
+ ld [Weather], a
+ ld a, 5
+ ld [WeatherCount], a
+ call AnimateCurrentMove
+ ld hl, SandstormBrewedText
+ jp StdBattleTextBox
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+; 37718
--- /dev/null
+++ b/engine/battle/move_effects/selfdestruct.asm
@@ -1,0 +1,31 @@
+BattleCommand_Selfdestruct: ; 37380
+ farcall StubbedTrainerRankings_Selfdestruct
+ ld a, BATTLEANIM_PLAYER_DAMAGE
+ ld [wNumHits], a
+ ld c, 3
+ call DelayFrames
+ ld a, BATTLE_VARS_STATUS
+ call GetBattleVarAddr
+ xor a
+ ld [hli], a
+ inc hl
+ ld [hli], a
+ ld [hl], a
+ ld a, $1
+ ld [wKickCounter], a
+ call BattleCommand_LowerSub
+ call LoadMoveAnim
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ res SUBSTATUS_LEECH_SEED, [hl]
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVarAddr
+ res SUBSTATUS_DESTINY_BOND, [hl]
+ call _CheckBattleScene
+ ret nc
+ farcall DrawPlayerHUD
+ farcall DrawEnemyHUD
+ call WaitBGMap
+ jp RefreshBattleHuds
+
+; 373c9
--- /dev/null
+++ b/engine/battle/move_effects/sketch.asm
@@ -1,0 +1,119 @@
+BattleCommand_Sketch: ; 35a74
+; sketch
+
+ call ClearLastMove
+; Don't sketch during a link battle
+ ld a, [wLinkMode]
+ and a
+ jr z, .not_linked
+ call AnimateFailedMove
+ jp PrintNothingHappened
+
+.not_linked
+; If the opponent has a substitute up, fail.
+ call CheckSubstituteOpp
+ jp nz, .fail
+; If the opponent is transformed, fail.
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_TRANSFORMED, [hl]
+ jp nz, .fail
+; Get the user's moveset in its party struct.
+; This move replacement shall be permanent.
+; Pointer will be in de.
+ ld a, MON_MOVES
+ call UserPartyAttr
+ ld d, h
+ ld e, l
+; Get the battle move structs.
+ ld hl, BattleMonMoves
+ ld a, [hBattleTurn]
+ and a
+ jr z, .get_last_move
+ ld hl, EnemyMonMoves
+.get_last_move
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ ld [wTypeMatchup], a
+ ld b, a
+; Fail if move is invalid or is Struggle.
+ and a
+ jr z, .fail
+ cp STRUGGLE
+ jr z, .fail
+; Fail if user already knows that move
+ ld c, NUM_MOVES
+.does_user_already_know_move
+ ld a, [hli]
+ cp b
+ jr z, .fail
+ dec c
+ jr nz, .does_user_already_know_move
+; Find Sketch in the user's moveset.
+; Pointer in hl, and index in c.
+ dec hl
+ ld c, NUM_MOVES
+.find_sketch
+ dec c
+ ld a, [hld]
+ cp SKETCH
+ jr nz, .find_sketch
+ inc hl
+; The Sketched move is loaded to that slot.
+ ld a, b
+ ld [hl], a
+; Copy the base PP from that move.
+ push bc
+ push hl
+ dec a
+ ld hl, Moves + MOVE_PP
+ call GetMoveAttr
+ pop hl
+ ld bc, BattleMonPP - BattleMonMoves
+ add hl, bc
+ ld [hl], a
+ pop bc
+
+ ld a, [hBattleTurn]
+ and a
+ jr z, .user_trainer
+ ld a, [wBattleMode]
+ dec a
+ jr nz, .user_trainer
+; wildmon
+ ld a, [hl]
+ push bc
+ ld hl, wWildMonPP
+ ld b, 0
+ add hl, bc
+ ld [hl], a
+ ld hl, wWildMonMoves
+ add hl, bc
+ pop bc
+ ld [hl], b
+ jr .done_copy
+
+.user_trainer
+ ld a, [hl]
+ push af
+ ld l, c
+ ld h, 0
+ add hl, de
+ ld a, b
+ ld [hl], a
+ pop af
+ ld de, MON_PP - MON_MOVES
+ add hl, de
+ ld [hl], a
+.done_copy
+ call GetMoveName
+ call AnimateCurrentMove
+
+ ld hl, SketchedText
+ jp StdBattleTextBox
+
+.fail
+ call AnimateFailedMove
+ jp PrintDidntAffect
+
+; 35b16
--- /dev/null
+++ b/engine/battle/move_effects/sleep_talk.asm
@@ -1,0 +1,145 @@
+BattleCommand_SleepTalk: ; 35b33
+; sleeptalk
+
+ call ClearLastMove
+ ld a, [AttackMissed]
+ and a
+ jr nz, .fail
+ ld a, [hBattleTurn]
+ and a
+ ld hl, BattleMonMoves + 1
+ ld a, [DisabledMove]
+ ld d, a
+ jr z, .got_moves
+ ld hl, EnemyMonMoves + 1
+ ld a, [EnemyDisabledMove]
+ ld d, a
+.got_moves
+ ld a, BATTLE_VARS_STATUS
+ call GetBattleVar
+ and SLP
+ jr z, .fail
+ ld a, [hl]
+ and a
+ jr z, .fail
+ call .safely_check_has_usable_move
+ jr c, .fail
+ dec hl
+.sample_move
+ push hl
+ call BattleRandom
+ maskbits NUM_MOVES
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ pop hl
+ and a
+ jr z, .sample_move
+ ld e, a
+ ld a, BATTLE_VARS_MOVE_ANIM
+ call GetBattleVar
+ cp e
+ jr z, .sample_move
+ ld a, e
+ cp d
+ jr z, .sample_move
+ call .check_two_turn_move
+ jr z, .sample_move
+ ld a, BATTLE_VARS_MOVE
+ call GetBattleVarAddr
+ ld a, e
+ ld [hl], a
+ call CheckUserIsCharging
+ jr nz, .charging
+ ld a, [wKickCounter]
+ push af
+ call BattleCommand_LowerSub
+ pop af
+ ld [wKickCounter], a
+.charging
+ call LoadMoveAnim
+ call UpdateMoveData
+ jp ResetTurn
+
+.fail
+ call AnimateFailedMove
+ jp TryPrintButItFailed
+
+.safely_check_has_usable_move
+ push hl
+ push de
+ push bc
+ call .check_has_usable_move
+ pop bc
+ pop de
+ pop hl
+ ret
+
+.check_has_usable_move
+ ld a, [hBattleTurn]
+ and a
+ ld a, [DisabledMove]
+ jr z, .got_move_2
+
+ ld a, [EnemyDisabledMove]
+.got_move_2
+ ld b, a
+ ld a, BATTLE_VARS_MOVE
+ call GetBattleVar
+ ld c, a
+ dec hl
+ ld d, NUM_MOVES
+.loop2
+ ld a, [hl]
+ and a
+ jr z, .carry
+
+ cp c
+ jr z, .nope
+ cp b
+ jr z, .nope
+
+ call .check_two_turn_move
+ jr nz, .no_carry
+
+.nope
+ inc hl
+ dec d
+ jr nz, .loop2
+
+.carry
+ scf
+ ret
+
+.no_carry
+ and a
+ ret
+
+.check_two_turn_move
+ push hl
+ push de
+ push bc
+
+ ld b, a
+ callfar GetMoveEffect
+ ld a, b
+
+ pop bc
+ pop de
+ pop hl
+
+ cp EFFECT_SKULL_BASH
+ ret z
+ cp EFFECT_RAZOR_WIND
+ ret z
+ cp EFFECT_SKY_ATTACK
+ ret z
+ cp EFFECT_SOLARBEAM
+ ret z
+ cp EFFECT_FLY
+ ret z
+ cp EFFECT_BIDE
+ ret
+
+; 35bff
--- /dev/null
+++ b/engine/battle/move_effects/snore.asm
@@ -1,0 +1,13 @@
+BattleCommand_Snore: ; 359d0
+; snore
+ ld a, BATTLE_VARS_STATUS
+ call GetBattleVar
+ and SLP
+ ret nz
+ call ResetDamage
+ ld a, $1
+ ld [AttackMissed], a
+ call FailMove
+ jp EndMoveEffect
+
+; 359e6
--- /dev/null
+++ b/engine/battle/move_effects/spikes.asm
@@ -1,0 +1,27 @@
+BattleCommand_Spikes: ; 37683
+; spikes
+
+ ld hl, EnemyScreens
+ ld a, [hBattleTurn]
+ and a
+ jr z, .asm_3768e
+ ld hl, PlayerScreens
+.asm_3768e
+
+; Fails if spikes are already down!
+
+ bit SCREENS_SPIKES, [hl]
+ jr nz, .failed
+
+; Nothing else stops it from working.
+
+ set SCREENS_SPIKES, [hl]
+
+ call AnimateCurrentMove
+
+ ld hl, SpikesText
+ jp StdBattleTextBox
+
+.failed
+ jp FailMove
+; 376a0
--- /dev/null
+++ b/engine/battle/move_effects/spite.asm
@@ -1,0 +1,88 @@
+BattleCommand_Spite: ; 35c0f
+; spite
+
+ ld a, [AttackMissed]
+ and a
+ jp nz, .failed
+ ld bc, PARTYMON_STRUCT_LENGTH ; ????
+ ld hl, EnemyMonMoves
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_moves
+ ld hl, BattleMonMoves
+.got_moves
+ ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
+ call GetBattleVar
+ and a
+ jr z, .failed
+ cp STRUGGLE
+ jr z, .failed
+ ld b, a
+ ld c, -1
+.loop
+ inc c
+ ld a, [hli]
+ cp b
+ jr nz, .loop
+ ld [wTypeMatchup], a
+ dec hl
+ ld b, 0
+ push bc
+ ld c, BattleMonPP - BattleMonMoves
+ add hl, bc
+ pop bc
+ ld a, [hl]
+ and PP_MASK
+ jr z, .failed
+ push bc
+ call GetMoveName
+ ; lose 2-5 PP
+ call BattleRandom
+ and %11
+ inc a
+ inc a
+ ld b, a
+ ld a, [hl]
+ and PP_MASK
+ cp b
+ jr nc, .deplete_pp
+ ld b, a
+.deplete_pp
+ ld a, [hl]
+ sub b
+ ld [hl], a
+ push af
+ ld a, MON_PP
+ call OpponentPartyAttr
+ ld d, b
+ pop af
+ pop bc
+ add hl, bc
+ ld e, a
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVar
+ bit SUBSTATUS_TRANSFORMED, a
+ jr nz, .transformed
+ ld a, [hBattleTurn]
+ and a
+ jr nz, .not_wildmon
+ ld a, [wBattleMode]
+ dec a
+ jr nz, .not_wildmon
+ ld hl, wWildMonPP
+ add hl, bc
+.not_wildmon
+ ld [hl], e
+.transformed
+ push de
+ call AnimateCurrentMove
+ pop de
+ ld a, d
+ ld [wTypeMatchup], a
+ ld hl, SpiteEffectText
+ jp StdBattleTextBox
+
+.failed
+ jp PrintDidntAffect2
+
+; 35c94
--- /dev/null
+++ b/engine/battle/move_effects/splash.asm
@@ -1,0 +1,6 @@
+BattleCommand_Splash: ; 36fe1
+ call AnimateCurrentMove
+ farcall StubbedTrainerRankings_Splash
+ jp PrintNothingHappened
+
+; 36fed
--- /dev/null
+++ b/engine/battle/move_effects/substitute.asm
@@ -1,0 +1,90 @@
+BattleCommand_Substitute: ; 36e7c
+; substitute
+
+ call BattleCommand_MoveDelay
+ ld hl, BattleMonMaxHP
+ ld de, PlayerSubstituteHP
+ ld a, [hBattleTurn]
+ and a
+ jr z, .got_hp
+ ld hl, EnemyMonMaxHP
+ ld de, EnemySubstituteHP
+.got_hp
+
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVar
+ bit SUBSTATUS_SUBSTITUTE, a
+ jr nz, .already_has_sub
+
+ ld a, [hli]
+ ld b, [hl]
+ srl a
+ rr b
+ srl a
+ rr b
+ dec hl
+ dec hl
+ ld a, b
+ ld [de], a
+ ld a, [hld]
+ sub b
+ ld e, a
+ ld a, [hl]
+ sbc 0
+ ld d, a
+ jr c, .too_weak_to_sub
+ ld a, d
+ or e
+ jr z, .too_weak_to_sub
+ ld [hl], d
+ inc hl
+ ld [hl], e
+
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ set SUBSTATUS_SUBSTITUTE, [hl]
+
+ ld hl, wPlayerWrapCount
+ ld de, wPlayerTrappingMove
+ ld a, [hBattleTurn]
+ and a
+ jr z, .player
+ ld hl, wEnemyWrapCount
+ ld de, wEnemyTrappingMove
+.player
+
+ xor a
+ ld [hl], a
+ ld [de], a
+ call _CheckBattleScene
+ jr c, .no_anim
+
+ xor a
+ ld [wNumHits], a
+ ld [FXAnimID + 1], a
+ ld [wKickCounter], a
+ ld a, SUBSTITUTE
+ call LoadAnim
+ jr .finish
+
+.no_anim
+ call BattleCommand_RaiseSubNoAnim
+.finish
+ ld hl, MadeSubstituteText
+ call StdBattleTextBox
+ jp RefreshBattleHuds
+
+.already_has_sub
+ call CheckUserIsCharging
+ call nz, BattleCommand_RaiseSub
+ ld hl, HasSubstituteText
+ jr .jp_stdbattletextbox
+
+.too_weak_to_sub
+ call CheckUserIsCharging
+ call nz, BattleCommand_RaiseSub
+ ld hl, TooWeakSubText
+.jp_stdbattletextbox
+ jp StdBattleTextBox
+
+; 36f0b
--- /dev/null
+++ b/engine/battle/move_effects/sunny_day.asm
@@ -1,0 +1,11 @@
+BattleCommand_StartSun: ; 37c07
+; startsun
+ ld a, WEATHER_SUN
+ ld [Weather], a
+ ld a, 5
+ ld [WeatherCount], a
+ call AnimateCurrentMove
+ ld hl, SunGotBrightText
+ jp StdBattleTextBox
+
+; 37c1a
--- /dev/null
+++ b/engine/battle/move_effects/teleport.asm
@@ -1,0 +1,91 @@
+BattleCommand_Teleport: ; 36778
+; teleport
+
+ ld a, [BattleType]
+ cp BATTLETYPE_SHINY
+ jr z, .failed
+ cp BATTLETYPE_TRAP
+ jr z, .failed
+ cp BATTLETYPE_CELEBI
+ jr z, .failed
+ cp BATTLETYPE_SUICUNE
+ jr z, .failed
+
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVar
+ bit SUBSTATUS_CANT_RUN, a
+ jr nz, .failed
+; Only need to check these next things if it's your turn
+ ld a, [hBattleTurn]
+ and a
+ jr nz, .enemy_turn
+; Can't teleport from a trainer battle
+ ld a, [wBattleMode]
+ dec a
+ jr nz, .failed
+; If your level is greater than the opponent's, you run without fail.
+ ld a, [CurPartyLevel]
+ ld b, a
+ ld a, [BattleMonLevel]
+ cp b
+ jr nc, .run_away
+; Generate a number between 0 and (YourLevel + TheirLevel).
+ add b
+ ld c, a
+ inc c
+.loop_player
+ call BattleRandom
+ cp c
+ jr nc, .loop_player
+; If that number is greater than 4 times your level, run away.
+ srl b
+ srl b
+ cp b
+ jr nc, .run_away
+
+.failed
+ call AnimateFailedMove
+ jp PrintButItFailed
+
+.enemy_turn
+ ld a, [wBattleMode]
+ dec a
+ jr nz, .failed
+ ld a, [BattleMonLevel]
+ ld b, a
+ ld a, [CurPartyLevel]
+ cp b
+ jr nc, .run_away
+ add b
+ ld c, a
+ inc c
+.loop_enemy
+ call BattleRandom
+ cp c
+ jr nc, .loop_enemy
+ srl b
+ srl b
+ cp b
+ ; This does the wrong thing. What was
+ ; probably intended was jr c, .failed
+ ; The way this is made makes enemy use
+ ; of Teleport always succeed if able
+ jr nc, .run_away
+.run_away
+ call UpdateBattleMonInParty
+ xor a
+ ld [wNumHits], a
+ inc a
+ ld [wForcedSwitch], a
+ ld [wKickCounter], a
+ call SetBattleDraw
+ call BattleCommand_LowerSub
+ call LoadMoveAnim
+ ld c, 20
+ call DelayFrames
+ call SetBattleDraw
+
+ ld hl, FledFromBattleText
+ jp StdBattleTextBox
+
+; 36804
--- /dev/null
+++ b/engine/battle/move_effects/thief.asm
@@ -1,0 +1,116 @@
+BattleCommand_Thief: ; 37492
+; thief
+
+ ld a, [hBattleTurn]
+ and a
+ jr nz, .enemy
+
+; The player needs to be able to steal an item.
+
+ call .playeritem
+ ld a, [hl]
+ and a
+ ret nz
+
+; The enemy needs to have an item to steal.
+
+ call .enemyitem
+ ld a, [hl]
+ and a
+ ret z
+
+; Can't steal mail.
+
+ ld [wd265], a
+ ld d, a
+ farcall ItemIsMail
+ ret c
+
+ ld a, [EffectFailed]
+ and a
+ ret nz
+
+ ld a, [wLinkMode]
+ and a
+ jr z, .stealenemyitem
+
+ ld a, [wBattleMode]
+ dec a
+ ret z
+
+.stealenemyitem
+ call .enemyitem
+ xor a
+ ld [hl], a
+ ld [de], a
+
+ call .playeritem
+ ld a, [wd265]
+ ld [hl], a
+ ld [de], a
+ jr .stole
+
+
+.enemy
+
+; The enemy can't already have an item.
+
+ call .enemyitem
+ ld a, [hl]
+ and a
+ ret nz
+
+; The player must have an item to steal.
+
+ call .playeritem
+ ld a, [hl]
+ and a
+ ret z
+
+; Can't steal mail!
+
+ ld [wd265], a
+ ld d, a
+ farcall ItemIsMail
+ ret c
+
+ ld a, [EffectFailed]
+ and a
+ ret nz
+
+; If the enemy steals your item,
+; it's gone for good if you don't get it back.
+
+ call .playeritem
+ xor a
+ ld [hl], a
+ ld [de], a
+
+ call .enemyitem
+ ld a, [wd265]
+ ld [hl], a
+ ld [de], a
+
+
+.stole
+ call GetItemName
+ ld hl, StoleText
+ jp StdBattleTextBox
+
+
+.playeritem
+ ld a, 1
+ call BattlePartyAttr
+ ld d, h
+ ld e, l
+ ld hl, BattleMonItem
+ ret
+
+.enemyitem
+ ld a, 1
+ call OTPartyAttr
+ ld d, h
+ ld e, l
+ ld hl, EnemyMonItem
+ ret
+; 37517
--- /dev/null
+++ b/engine/battle/move_effects/thunder.asm
@@ -1,0 +1,20 @@
+BattleCommand_ThunderAccuracy: ; 37d94
+; thunderaccuracy
+
+ ld a, BATTLE_VARS_MOVE_TYPE
+ call GetBattleVarAddr
+ inc hl
+ ld a, [Weather]
+ cp WEATHER_RAIN
+ jr z, .rain
+ cp WEATHER_SUN
+ ret nz
+ ld [hl], 50 percent + 1
+ ret
+
+.rain
+ ; Redundant with CheckHit guranteeing hit
+ ld [hl], 100 percent
+ ret
+
+; 37daa
--- /dev/null
+++ b/engine/battle/move_effects/transform.asm
@@ -1,0 +1,141 @@
+
+BattleCommand_Transform: ; 371cd
+; transform
+
+ call ClearLastMove
+ ld a, BATTLE_VARS_SUBSTATUS5_OPP
+ call GetBattleVarAddr
+ bit SUBSTATUS_TRANSFORMED, [hl]
+ jp nz, BattleEffect_ButItFailed
+ call CheckHiddenOpponent
+ jp nz, BattleEffect_ButItFailed
+ xor a
+ ld [wNumHits], a
+ ld [FXAnimID + 1], a
+ ld a, $1
+ ld [wKickCounter], a
+ ld a, BATTLE_VARS_SUBSTATUS4
+ call GetBattleVarAddr
+ bit SUBSTATUS_SUBSTITUTE, [hl]
+ push af
+ jr z, .mimic_substitute
+ call CheckUserIsCharging
+ jr nz, .mimic_substitute
+ ld a, SUBSTITUTE
+ call LoadAnim
+.mimic_substitute
+ ld a, BATTLE_VARS_SUBSTATUS5
+ call GetBattleVarAddr
+ set SUBSTATUS_TRANSFORMED, [hl]
+ call ResetActorDisable
+ ld hl, BattleMonSpecies
+ ld de, EnemyMonSpecies
+ ld a, [hBattleTurn]
+ and a
+ jr nz, .got_mon_species
+ ld hl, EnemyMonSpecies
+ ld de, BattleMonSpecies
+ xor a
+ ld [CurMoveNum], a
+.got_mon_species
+ push hl
+ ld a, [hli]
+ ld [de], a
+ inc hl
+ inc de
+ inc de
+ ld bc, NUM_MOVES
+ call CopyBytes
+ ld a, [hBattleTurn]
+ and a
+ jr z, .mimic_enemy_backup
+ ld a, [de]
+ ld [wEnemyBackupDVs], a
+ inc de
+ ld a, [de]
+ ld [wEnemyBackupDVs + 1], a
+ dec de
+.mimic_enemy_backup
+; copy DVs
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hli]
+ ld [de], a
+ inc de
+; move pointer to stats
+ ld bc, BattleMonStats - BattleMonPP
+ add hl, bc
+ push hl
+ ld h, d
+ ld l, e
+ add hl, bc
+ ld d, h
+ ld e, l
+ pop hl
+ ld bc, BattleMonStructEnd - BattleMonStats
+ call CopyBytes
+; init the power points
+ ld bc, BattleMonMoves - BattleMonStructEnd
+ add hl, bc
+ push de
+ ld d, h
+ ld e, l
+ pop hl
+ ld bc, BattleMonPP - BattleMonStructEnd
+ add hl, bc
+ ld b, NUM_MOVES
+.pp_loop
+ ld a, [de]
+ inc de
+ and a
+ jr z, .done_move
+ cp SKETCH
+ ld a, 1
+ jr z, .done_move
+ ld a, 5
+.done_move
+ ld [hli], a
+ dec b
+ jr nz, .pp_loop
+ pop hl
+ ld a, [hl]
+ ld [wNamedObjectIndexBuffer], a
+ call GetPokemonName
+ ld hl, EnemyStats
+ ld de, PlayerStats
+ ld bc, 2 * 5
+ call BattleSideCopy
+ ld hl, EnemyStatLevels
+ ld de, PlayerStatLevels
+ ld bc, 8
+ call BattleSideCopy
+ call _CheckBattleScene
+ jr c, .mimic_anims
+ ld a, [hBattleTurn]
+ and a
+ ld a, [wPlayerMinimized]
+ jr z, .got_byte
+ ld a, [wEnemyMinimized]
+.got_byte
+ and a
+ jr nz, .mimic_anims
+ call LoadMoveAnim
+ jr .after_anim
+
+.mimic_anims
+ call BattleCommand_MoveDelay
+ call BattleCommand_RaiseSubNoAnim
+.after_anim
+ xor a
+ ld [wNumHits], a
+ ld [FXAnimID + 1], a
+ ld a, $2
+ ld [wKickCounter], a
+ pop af
+ ld a, SUBSTITUTE
+ call nz, LoadAnim
+ ld hl, TransformedText
+ jp StdBattleTextBox
+
+; 372c6
--- /dev/null
+++ b/engine/battle/move_effects/triple_kick.asm
@@ -1,0 +1,39 @@
+BattleCommand_TripleKick: ; 346b2
+; triplekick
+
+ ld a, [wKickCounter]
+ ld b, a
+ inc b
+ ld hl, CurDamage + 1
+ ld a, [hld]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+.next_kick
+ dec b
+ ret z
+ ld a, [hl]
+ add e
+ ld [hld], a
+ ld a, [hl]
+ adc d
+ ld [hli], a
+
+; No overflow.
+ jr nc, .next_kick
+ ld a, $ff
+ ld [hld], a
+ ld [hl], a
+ ret
+
+; 346cd
+
+
+BattleCommand_KickCounter: ; 346cd
+; kickcounter
+
+ ld hl, wKickCounter
+ inc [hl]
+ ret
+
+; 346d2