shithub: pokecrystal

Download patch

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/

diff: cannot open a/engine/battle/effect_commands//null: file does not exist: 'a/engine/battle/effect_commands//null' diff: cannot open b/engine/battle/move_effects//null: file does not exist: 'b/engine/battle/move_effects//null'
--- 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