First Commit

Upload literally everything from the pokecrystal16 expand-move-ID branch
This commit is contained in:
Zeta_Null 2023-09-10 12:35:35 -04:00
commit 2f8a41f833
4618 changed files with 480386 additions and 0 deletions

View file

@ -0,0 +1,75 @@
BattleCommand_Attract:
ld a, [wAttackMissed]
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
CheckOppositeGender:
ld a, MON_SPECIES
call BattlePartyAttr
ld a, [hl]
ld [wCurPartySpecies], a
ld a, [wCurBattleMon]
ld [wCurPartyMon], a
xor a
ld [wMonType], a
farcall GetGender
jr c, .genderless_samegender
ld b, 1
jr nz, .got_gender
dec b
.got_gender
push bc
ld a, [wTempEnemyMonSpecies]
ld [wCurPartySpecies], a
ld hl, wEnemyMonDVs
ld a, [wEnemySubStatus5]
bit SUBSTATUS_TRANSFORMED, a
jr z, .not_transformed
ld hl, wEnemyBackupDVs
.not_transformed
ld a, [hli]
ld [wTempMonDVs], a
ld a, [hl]
ld [wTempMonDVs + 1], a
ld a, TEMPMON
ld [wMonType], 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

View file

@ -0,0 +1,215 @@
BattleCommand_BatonPass:
ldh 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
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, TRUE
ld [wApplyStatLevelMultipliersToEnemy], a
ld hl, ApplyStatLevelMultiplierOnAllStats
call CallBattleCore
ld hl, SpikesDamage
call CallBattleCore
jr ResetBatonPassStatus
BatonPass_LinkPlayerSwitch:
ld a, [wLinkMode]
and a
ret z
ld a, BATTLEPLAYERACTION_USEITEM
ld [wBattlePlayerAction], a
call LoadStandardMenuHeader
ld hl, LinkBattleSendReceiveAction
call CallBattleCore
call CloseWindow
xor a ; BATTLEPLAYERACTION_USEMOVE
ld [wBattlePlayerAction], a
ret
BatonPass_LinkEnemySwitch:
ld a, [wLinkMode]
and a
ret z
call LoadStandardMenuHeader
ld hl, LinkBattleSendReceiveAction
call CallBattleCore
ld a, [wOTPartyCount]
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, [wCurOTMon]
add BATTLEACTION_SWITCH1
ld [wBattleAction], a
.switch
jp CloseWindow
FailedBatonPass:
call AnimateFailedMove
jp PrintButItFailed
ResetBatonPassStatus:
; Reset status changes that aren't passed by Baton Pass.
; Nightmare isn't passed.
ld a, BATTLE_VARS_STATUS
call GetBattleVar
and SLP_MASK
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, wPlayerSubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ld hl, wEnemySubStatus1
res SUBSTATUS_IN_LOVE, [hl]
ld hl, wPlayerSubStatus5
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
CheckAnyOtherAlivePartyMons:
ld hl, wPartyMon1HP
ld a, [wPartyCount]
ld d, a
ld a, [wCurBattleMon]
ld e, a
jr CheckAnyOtherAliveMons
CheckAnyOtherAliveEnemyMons:
ld hl, wOTPartyMon1HP
ld a, [wOTPartyCount]
ld d, a
ld a, [wCurOTMon]
ld e, a
; fallthrough
CheckAnyOtherAliveMons:
; 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

View file

@ -0,0 +1,220 @@
BattleCommand_BeatUp:
call ResetDamage
ldh a, [hBattleTurn]
and a
jp nz, .enemy_beats_up
ld a, [wPlayerSubStatus3]
bit SUBSTATUS_IN_LOOP, a
jr nz, .next_mon
ld c, 20
call DelayFrames
xor a
ld [wPlayerRolloutCount], a
ld [wCurBeatUpPartyMon], a
ld [wBeatUpHitAtLeastOnce], a
jr .got_mon
.next_mon
ld a, [wPlayerRolloutCount]
ld b, a
ld a, [wPartyCount]
sub b
ld [wCurBeatUpPartyMon], a
.got_mon
; BUG: Beat Up can desynchronize link battles (see docs/bugs_and_glitches.md)
ld a, [wCurBeatUpPartyMon]
ld hl, wPartyMonNicknames
call GetNickname
ld a, MON_HP
call GetBeatupMonLocation
ld a, [hli]
or [hl]
jp z, .beatup_fail ; fainted
ld a, [wCurBeatUpPartyMon]
ld c, a
ld a, [wCurBattleMon]
cp [hl]
ld hl, wBattleMonStatus
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, [wEnemyMonSpecies]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseDefense]
ld c, a
push bc
ld a, MON_SPECIES
call GetBeatupMonLocation
ld a, [hl]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseAttack]
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, [wEnemySubStatus3]
bit SUBSTATUS_IN_LOOP, a
jr nz, .enemy_next_mon
xor a
ld [wEnemyRolloutCount], a
ld [wCurBeatUpPartyMon], a
ld [wBeatUpHitAtLeastOnce], a
jr .enemy_got_mon
.enemy_next_mon
ld a, [wEnemyRolloutCount]
ld b, a
ld a, [wOTPartyCount]
sub b
ld [wCurBeatUpPartyMon], a
.enemy_got_mon
ld a, [wBattleMode]
dec a
jr z, .wild
ld a, [wLinkMode]
and a
jr nz, .link_or_tower
ld a, [wInBattleTowerBattle]
and a
jr nz, .link_or_tower
ld a, [wCurBeatUpPartyMon]
ld c, a
ld b, 0
ld hl, wOTPartySpecies
add hl, bc
ld a, [hl]
ld [wNamedObjectIndex], a
call GetPokemonName
jr .got_enemy_nick
.link_or_tower
ld a, [wCurBeatUpPartyMon]
ld hl, wOTPartyMonNicknames
ld bc, NAME_LENGTH
call AddNTimes
ld de, wStringBuffer1
call CopyBytes
.got_enemy_nick
ld a, MON_HP
call GetBeatupMonLocation
ld a, [hli]
or [hl]
jp z, .beatup_fail
ld a, [wCurBeatUpPartyMon]
ld b, a
ld a, [wCurOTMon]
cp b
ld hl, wEnemyMonStatus
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, [wEnemyMonSpecies]
ld [wNamedObjectIndex], a
call GetPokemonName
ld hl, BeatUpAttackText
call StdBattleTextbox
jp EnemyAttackDamage
.finish_beatup
ld hl, BeatUpAttackText
call StdBattleTextbox
ld a, [wBattleMonSpecies]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseDefense]
ld c, a
push bc
ld a, MON_SPECIES
call GetBeatupMonLocation
ld a, [hl]
ld [wCurSpecies], a
call GetBaseData
ld a, [wBaseAttack]
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
.beatup_fail
ld b, buildopponentrage_command
jp SkipToBattleCommand
BattleCommand_BeatUpFailText:
; BUG: Beat Up may trigger King's Rock even if it failed (see docs/bugs_and_glitches.md)
ld a, [wBeatUpHitAtLeastOnce]
and a
ret nz
jp PrintButItFailed
GetBeatupMonLocation:
push bc
ld c, a
ld b, 0
ldh a, [hBattleTurn]
and a
ld hl, wPartyMon1Species
jr z, .got_species
ld hl, wOTPartyMon1Species
.got_species
ld a, [wCurBeatUpPartyMon]
add hl, bc
call GetPartyLocation
pop bc
ret

View file

@ -0,0 +1,31 @@
BattleCommand_BellyDrum:
; BUG: Belly Drum sharply boosts Attack even with under 50% HP (see docs/bugs_and_glitches.md)
call BattleCommand_AttackUp2
ld a, [wAttackMissed]
and a
jr nz, .failed
callfar GetHalfMaxHP
callfar CheckUserHasEnoughHP
jr nc, .failed
push bc
call AnimateCurrentMove
pop bc
callfar SubtractHPFromUser
call UpdateUserInParty
ld a, MAX_STAT_LEVEL - BASE_STAT_LEVEL - 1
.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

View file

@ -0,0 +1,99 @@
BattleCommand_StoreEnergy:
ld a, BATTLE_VARS_SUBSTATUS3
call GetBattleVar
bit SUBSTATUS_BIDE, a
ret z
ld hl, wPlayerRolloutCount
ldh a, [hBattleTurn]
and a
jr z, .check_still_storing_energy
ld hl, wEnemyRolloutCount
.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, wPlayerDamageTaken + 1
ld de, wPlayerCharging ; player
ldh a, [hBattleTurn]
and a
jr z, .player
ld hl, wEnemyDamageTaken + 1
ld de, wEnemyCharging ; enemy
.player
ld a, [hld]
add a
ld b, a
ld [wCurDamage + 1], a
ld a, [hl]
rl a
ld [wCurDamage], a
jr nc, .not_maxed
ld a, $ff
ld [wCurDamage], a
ld [wCurDamage + 1], a
.not_maxed
or b
jr nz, .built_up_something
ld a, 1
ld [wAttackMissed], a
.built_up_something
xor a
ld [hli], a
ld [hl], a
ld [de], a
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVarAddr
push hl
ld hl, BIDE
call GetMoveIDFromIndex
pop hl
ld [hl], a
ld b, unleashenergy_command
jp SkipToBattleCommand
.still_storing
ld hl, StoringEnergyText
call StdBattleTextbox
jp EndMoveEffect
BattleCommand_UnleashEnergy:
ld de, wPlayerDamageTaken
ld bc, wPlayerRolloutCount
ldh a, [hBattleTurn]
and a
jr z, .got_damage
ld de, wEnemyDamageTaken
ld bc, wEnemyRolloutCount
.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 [wBattleAnimParam], a
call AnimateCurrentMove
jp EndMoveEffect

View file

@ -0,0 +1,94 @@
BattleCommand_Conversion:
ld hl, wBattleMonMoves
ld de, wBattleMonType1
ldh a, [hBattleTurn]
and a
jr z, .got_moves
ld hl, wEnemyMonMoves
ld de, wEnemyMonType1
.got_moves
push de
ld c, 0
ld de, wStringBuffer1
.loop
push hl
ld b, 0
add hl, bc
ld a, [hl]
pop hl
and a
jr z, .okay
push hl
push bc
ld l, a
ld a, MOVE_TYPE
call GetMoveAttribute
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, wStringBuffer1
.loop2
ld a, [hl]
cp -1
jr z, .fail
cp CURSE_TYPE
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, wStringBuffer1
add hl, bc
ld a, [hl]
cp -1
jr z, .loop3
cp CURSE_TYPE
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 [wNamedObjectIndex], a
farcall GetTypeName
call AnimateCurrentMove
ld hl, TransformedTypeText
jp StdBattleTextbox

View file

@ -0,0 +1,62 @@
BattleCommand_Conversion2:
ld a, [wAttackMissed]
and a
jr nz, .failed
ld hl, wBattleMonType1
ldh a, [hBattleTurn]
and a
jr z, .got_type
ld hl, wEnemyMonType1
.got_type
ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
call GetBattleVar
and a
jr z, .failed
push hl
ld l, a
ld a, MOVE_TYPE
call GetMoveAttribute
ld d, a
pop hl
cp CURSE_TYPE
jr z, .failed
call AnimateCurrentMove
call BattleCommand_SwitchTurn
.loop
call BattleRandom
maskbits TYPES_END
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 EFFECTIVE
jr nc, .loop
call BattleCommand_SwitchTurn
ld a, [hl]
ld [wNamedObjectIndex], a
predef GetTypeName
ld hl, TransformedTypeText
jp StdBattleTextbox
.failed
jp FailMove

View file

@ -0,0 +1,56 @@
BattleCommand_Counter:
ld a, 1
ld [wAttackMissed], 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
ld de, wStringBuffer1
call GetMoveData
ld a, [wStringBuffer1 + MOVE_POWER]
and a
ret z
ld a, [wStringBuffer1 + MOVE_TYPE]
cp SPECIAL
ret nc
; BUG: Counter and Mirror Coat still work if the opponent uses an item (see docs/bugs_and_glitches.md)
ld hl, wCurDamage
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 [wAttackMissed], a
ret

View file

@ -0,0 +1,91 @@
BattleCommand_Curse:
ld de, wBattleMonType1
ld bc, wPlayerStatLevels
ldh a, [hBattleTurn]
and a
jr z, .go
ld de, wEnemyMonType1
ld bc, wEnemyStatLevels
.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 [wBattleAnimParam], 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

View file

@ -0,0 +1,7 @@
BattleCommand_DestinyBond:
ld a, BATTLE_VARS_SUBSTATUS5
call GetBattleVarAddr
set SUBSTATUS_DESTINY_BOND, [hl]
call AnimateCurrentMove
ld hl, DestinyBondEffectText
jp StdBattleTextbox

View file

@ -0,0 +1,73 @@
BattleCommand_Disable:
ld a, [wAttackMissed]
and a
jr nz, .failed
ld de, wEnemyDisableCount
ld hl, wEnemyMonMoves
ldh a, [hBattleTurn]
and a
jr z, .got_moves
ld de, wPlayerDisableCount
ld hl, wBattleMonMoves
.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
ld b, a
push bc
ld bc, STRUGGLE
call CompareMove
pop bc
jr z, .failed
ld c, $ff
.loop
inc c
ld a, [hli]
cp b
jr nz, .loop
ldh a, [hBattleTurn]
and a
ld hl, wEnemyMonPP
jr z, .got_pp
ld hl, wBattleMonPP
.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, wDisabledMove
ldh 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 [wNamedObjectIndex], a
call GetMoveName
ld hl, WasDisabledText
jp StdBattleTextbox
.failed
jp FailMove

View file

@ -0,0 +1,120 @@
BattleCommand_Encore:
ld hl, wEnemyMonMoves
ld de, wEnemyEncoreCount
ldh a, [hBattleTurn]
and a
jr z, .ok
ld hl, wBattleMonMoves
ld de, wPlayerEncoreCount
.ok
ld a, BATTLE_VARS_LAST_MOVE_OPP
call GetBattleVar
ld b, a
push hl
ld hl, .invalid_moves
call CheckMoveInList
pop hl
jp c, .failed
.got_move
ld a, [hli]
cp b
jr nz, .got_move
ld bc, wBattleMonPP - wBattleMonMoves - 1
add hl, bc
ld a, [hl]
and PP_MASK
jp z, .failed
ld a, [wAttackMissed]
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
ldh a, [hBattleTurn]
and a
jr z, .force_last_enemy_move
push hl
ld a, [wLastPlayerMove]
ld b, a
ld c, 0
ld hl, wBattleMonMoves
.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 [wCurMoveNum], a
ld a, b
ld [wCurPlayerMove], a
ld de, wPlayerMoveStruct
call GetMoveData
jr .finish_move
.force_last_enemy_move
push hl
ld a, [wLastEnemyMove]
ld b, a
ld c, 0
ld hl, wEnemyMonMoves
.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 [wCurEnemyMoveNum], a
ld a, b
ld [wCurEnemyMove], a
ld de, wEnemyMoveStruct
call GetMoveData
.finish_move
call AnimateCurrentMove
ld hl, GotAnEncoreText
jp StdBattleTextbox
.failed
jp PrintDidntAffect2
.invalid_moves
dw NO_MOVE
dw STRUGGLE
dw ENCORE
dw MIRROR_MOVE
dw -1

View file

@ -0,0 +1,14 @@
BattleCommand_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

View file

@ -0,0 +1,46 @@
BattleCommand_FalseSwipe:
; Makes sure wCurDamage < MonHP
ld hl, wEnemyMonHP
ldh a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wBattleMonHP
.got_hp
ld de, wCurDamage
ld c, 2
push hl
push de
call CompareBytes
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, [wCriticalHit]
cp 2
jr nz, .carry
xor a
ld [wCriticalHit], a
.carry
scf
ret
.done
and a
ret

View file

@ -0,0 +1,13 @@
BattleCommand_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

View file

@ -0,0 +1,20 @@
BattleCommand_Foresight:
ld a, [wAttackMissed]
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

View file

@ -0,0 +1,26 @@
BattleCommand_FrustrationPower:
; BUG: Return and Frustration deal no damage when the user's happiness is low or high, respectively (see docs/bugs_and_glitches.md)
push bc
ld hl, wBattleMonHappiness
ldh a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonHappiness
.ok
ld a, $ff
sub [hl]
ldh [hMultiplicand + 2], a
xor a
ldh [hMultiplicand + 0], a
ldh [hMultiplicand + 1], a
ld a, 10
ldh [hMultiplier], a
call Multiply
ld a, 25
ldh [hDivisor], a
ld b, 4
call Divide
ldh a, [hQuotient + 3]
ld d, a
pop bc
ret

View file

@ -0,0 +1,53 @@
BattleCommand_FuryCutter:
ld hl, wPlayerFuryCutterCount
ldh a, [hBattleTurn]
and a
jr z, .go
ld hl, wEnemyFuryCutterCount
.go
ld a, [wAttackMissed]
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, wCurDamage + 1
sla [hl]
dec hl
rl [hl]
jr nc, .checkdouble
; No overflow
ld a, $ff
ld [hli], a
ld [hl], a
ret
ResetFuryCutterCount:
push hl
ld hl, wPlayerFuryCutterCount
ldh a, [hBattleTurn]
and a
jr z, .reset
ld hl, wEnemyFuryCutterCount
.reset
xor a
ld [hl], a
pop hl
ret

View file

@ -0,0 +1,77 @@
BattleCommand_CheckFutureSight:
ld hl, wPlayerFutureSightCount
ld de, wPlayerFutureSightDamage
ldh 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 [wCurDamage], a
ld a, [de]
ld [wCurDamage + 1], a
ld b, futuresight_command
jp SkipToBattleCommand
BattleCommand_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
ldh 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
ldh a, [hBattleTurn]
and a
jr z, .StoreDamage
ld de, wEnemyFutureSightDamage
.StoreDamage:
ld hl, wCurDamage
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

View file

@ -0,0 +1,32 @@
BattleCommand_HealBell:
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVarAddr
res SUBSTATUS_NIGHTMARE, [hl]
ld de, wPartyMon1Status
ldh a, [hBattleTurn]
and a
jr z, .got_status
ld de, wOTPartyMon1Status
.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
ldh a, [hBattleTurn]
and a
jp z, CalcPlayerStats
jp CalcEnemyStats

View file

@ -0,0 +1,6 @@
BattleCommand_HiddenPower:
ld a, [wAttackMissed]
and a
ret nz
farcall HiddenPowerDamage
ret

View file

@ -0,0 +1,39 @@
BattleCommand_LeechSeed:
ld a, [wAttackMissed]
and a
jr nz, .evaded
call CheckSubstituteOpp
jr nz, .evaded
ld de, wEnemyMonType1
ldh a, [hBattleTurn]
and a
jr z, .ok
ld de, wBattleMonType1
.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

View file

@ -0,0 +1,19 @@
BattleCommand_LockOn:
call CheckSubstituteOpp
jr nz, .fail
ld a, [wAttackMissed]
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

View file

@ -0,0 +1,27 @@
BattleCommand_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 [wTextDecimalByte], a
call BattleCommand_MoveDelay
ld hl, MagnitudeText
call StdBattleTextbox
pop de
pop bc
ret
INCLUDE "data/moves/magnitude_power.asm"

View file

@ -0,0 +1,70 @@
BattleCommand_Metronome:
call ClearLastMove
call CheckUserIsCharging
jr nz, .charging
ld a, [wBattleAnimParam]
push af
call BattleCommand_LowerSub
pop af
ld [wBattleAnimParam], a
.charging
call LoadMoveAnim
.GetMove:
call ChooseRandomMove
; None of the moves in MetronomeExcepts.
ld de, 2
ld hl, MetronomeExcepts
call IsInWordArray
jr c, .GetMove
ld h, b
ld l, c
call GetMoveIDFromIndex
; No moves the user already has.
ld b, a
call CheckUserMove
jr z, .GetMove
ld a, BATTLE_VARS_MOVE
call GetBattleVarAddr
ld [hl], b
call UpdateMoveData
jp ResetTurn
ChooseRandomMove:
; chooses a random valid move and returns it in bc
call BattleRandom
if HIGH(NUM_ATTACKS)
maskbits HIGH(NUM_ATTACKS) + 1
if HIGH(NUM_ATTACKS) & (HIGH(NUM_ATTACKS) + 1)
; if HIGH(NUM_ATTACKS) is not one less than a power of two
cp HIGH(NUM_ATTACKS) + 1
jr nc, ChooseRandomMove
endc
ld b, a
call BattleRandom
ld c, a
or b
jr z, ChooseRandomMove
if LOW(NUM_ATTACKS) != $ff
ld a, b
cp HIGH(NUM_ATTACKS)
ret nz
ld a, c
cp LOW(NUM_ATTACKS) + 1
jr nc, ChooseRandomMove
endc
else
cp NUM_ATTACKS
jr nc, ChooseRandomMove
inc a
ld c, a
ld b, 0
endc
ret
INCLUDE "data/moves/metronome_exception_moves.asm"

View file

@ -0,0 +1,53 @@
BattleCommand_Mimic:
call ClearLastMove
call BattleCommand_MoveDelay
ld a, [wAttackMissed]
and a
jr nz, .fail
ld hl, wBattleMonMoves
ldh a, [hBattleTurn]
and a
jr z, .player_turn
ld hl, wEnemyMonMoves
.player_turn
call CheckHiddenOpponent
jr nz, .fail
ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
call GetBattleVar
and a
jr z, .fail
ld b, a
push bc
ld bc, STRUGGLE
call CompareMove
pop bc
jr z, .fail
ld c, NUM_MOVES
.check_already_knows_move
ld a, [hli]
cp b
jr z, .fail
dec c
jr nz, .check_already_knows_move
push hl
ld hl, MIMIC
call GetMoveIDFromIndex
pop hl
.find_mimic
dec hl
cp [hl]
jr nz, .find_mimic
ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
call GetBattleVar
ld [hl], a
ld [wNamedObjectIndex], a
ld bc, wBattleMonPP - wBattleMonMoves
add hl, bc
ld [hl], 5
call GetMoveName
call AnimateCurrentMove
ld hl, MimicLearnedMoveText
jp StdBattleTextbox
.fail
jp FailMimic

View file

@ -0,0 +1,57 @@
BattleCommand_MirrorCoat:
ld a, 1
ld [wAttackMissed], 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
ld de, wStringBuffer1
call GetMoveData
ld a, [wStringBuffer1 + MOVE_POWER]
and a
ret z
ld a, [wStringBuffer1 + MOVE_TYPE]
cp SPECIAL
ret c
; BUG: Counter and Mirror Coat still work if the opponent uses an item (see docs/bugs_and_glitches.md)
ld hl, wCurDamage
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 [wAttackMissed], a
ret

View file

@ -0,0 +1,48 @@
BattleCommand_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 [wNamedObjectIndex], a
push af
ld a, BATTLE_VARS_MOVE_ANIM
call GetBattleVarAddr
ld d, h
ld e, l
pop af
call GetMoveData
call GetMoveName
call CopyName1
call CheckUserIsCharging
jr nz, .done
ld a, [wBattleAnimParam]
push af
call BattleCommand_LowerSub
pop af
ld [wBattleAnimParam], a
.done
call BattleCommand_MoveDelay
jp ResetTurn

View file

@ -0,0 +1,13 @@
BattleCommand_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

View file

@ -0,0 +1,35 @@
BattleCommand_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_MASK
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

View file

@ -0,0 +1,91 @@
BattleCommand_PainSplit:
ld a, [wAttackMissed]
and a
jp nz, .ButItFailed
call CheckSubstituteOpp
jp nz, .ButItFailed
call AnimateCurrentMove
ld hl, wBattleMonMaxHP + 1
ld de, wEnemyMonMaxHP + 1
call .PlayerShareHP
ld a, $1
ld [wWhichHPBar], a
hlcoord 10, 9
predef AnimateHPBar
ld hl, wEnemyMonHP
ld a, [hli]
ld [wHPBuffer2 + 1], a
ld a, [hli]
ld [wHPBuffer2], a
ld a, [hli]
ld [wHPBuffer1 + 1], a
ld a, [hl]
ld [wHPBuffer1], 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 [wHPBuffer1], a
ld a, [hld]
ld [wHPBuffer1 + 1], a
ld a, [hld]
ld b, a
ld [wHPBuffer2], a
ld a, [hl]
ld [wHPBuffer2 + 1], a
dec de
dec de
ld a, [de]
dec de
add b
ld [wCurDamage + 1], a
ld b, [hl]
ld a, [de]
adc b
srl a
ld [wCurDamage], a
ld a, [wCurDamage + 1]
rr a
ld [wCurDamage + 1], a
inc hl
inc hl
inc hl
inc de
inc de
inc de
.EnemyShareHP:
ld c, [hl]
dec hl
ld a, [wCurDamage + 1]
sub c
ld b, [hl]
dec hl
ld a, [wCurDamage]
sbc b
jr nc, .skip
ld a, [wCurDamage]
ld b, a
ld a, [wCurDamage + 1]
ld c, a
.skip
ld a, c
ld [hld], a
ld [wHPBuffer3], a
ld a, b
ld [hli], a
ld [wHPBuffer3 + 1], a
ret
.ButItFailed:
jp PrintDidntAffect2

View file

@ -0,0 +1,24 @@
BattleCommand_PayDay:
xor a
ld hl, wStringBuffer1
ld [hli], a
ldh a, [hBattleTurn]
and a
ld a, [wBattleMonLevel]
jr z, .ok
ld a, [wEnemyMonLevel]
.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

View file

@ -0,0 +1,36 @@
BattleCommand_PerishSong:
ld hl, wPlayerSubStatus1
ld de, wEnemySubStatus1
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 [wPlayerPerishCount], a
.enemy
ld a, [de]
bit SUBSTATUS_PERISH, a
jr nz, .done
set SUBSTATUS_PERISH, a
ld [de], a
ld a, 4
ld [wEnemyPerishCount], a
.done
call AnimateCurrentMove
ld hl, StartPerishText
jp StdBattleTextbox
.failed
call AnimateFailedMove
jp PrintButItFailed

View file

@ -0,0 +1,87 @@
BattleCommand_Present:
; BUG: Present damage is incorrect in link battles (see docs/bugs_and_glitches.md)
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, [wAttackMissed]
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
cp b
jr nc, .got_power
inc c
inc hl
jr .next
.got_power
ld a, c
ld [wBattleAnimParam], a
call AnimateCurrentMoveEitherSide
ld d, [hl]
pop bc
ret
.heal_effect
pop bc
ld a, $3 ; heal animation
ld [wBattleAnimParam], a
call AnimateCurrentMove
call BattleCommand_SwitchTurn
ld hl, AICheckPlayerMaxHP
ldh a, [hBattleTurn]
and a
jr z, .got_hp_fn_pointer
ld hl, AICheckEnemyMaxHP
.got_hp_fn_pointer
ld a, BANK(AICheckPlayerMaxHP) ; aka BANK(AICheckEnemyMaxHP)
rst FarCall
jr c, .already_fully_healed
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
.already_fully_healed
call BattleCommand_SwitchTurn
call _CheckBattleScene
jr nc, .do_animation
call AnimateFailedMove
ld hl, PresentFailedText
call StdBattleTextbox
.do_animation
jp EndMoveEffect
INCLUDE "data/moves/present_power.asm"

View file

@ -0,0 +1,74 @@
BattleCommand_Protect:
call ProtectChance
ret c
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVarAddr
set SUBSTATUS_PROTECT, [hl]
call AnimateCurrentMove
ld hl, ProtectedItselfText
jp StdBattleTextbox
ProtectChance:
ld de, wPlayerProtectCount
ldh a, [hBattleTurn]
and a
jr z, .got_count
ld de, wEnemyProtectCount
.got_count
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

View file

@ -0,0 +1,47 @@
BattleCommand_PsychUp:
ld hl, wEnemyStatLevels
ld de, wPlayerStatLevels
ldh 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
ldh 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

View file

@ -0,0 +1,23 @@
BattleCommand_Pursuit:
; Double damage if the opponent is switching.
ld hl, wEnemyIsSwitching
ldh a, [hBattleTurn]
and a
jr z, .ok
ld hl, wPlayerIsSwitching
.ok
ld a, [hl]
and a
ret z
ld hl, wCurDamage + 1
sla [hl]
dec hl
rl [hl]
ret nc
ld a, $ff
ld [hli], a
ld [hl], a
ret

View file

@ -0,0 +1,5 @@
BattleCommand_Rage:
ld a, BATTLE_VARS_SUBSTATUS4
call GetBattleVarAddr
set SUBSTATUS_RAGE, [hl]
ret

View file

@ -0,0 +1,8 @@
BattleCommand_StartRain:
ld a, WEATHER_RAIN
ld [wBattleWeather], a
ld a, 5
ld [wWeatherCount], a
call AnimateCurrentMove
ld hl, DownpourText
jp StdBattleTextbox

View file

@ -0,0 +1,34 @@
BattleCommand_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, wPlayerScreens
ld de, wPlayerWrapCount
ldh a, [hBattleTurn]
and a
jr z, .got_screens_wrap
ld hl, wEnemyScreens
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

View file

@ -0,0 +1,25 @@
BattleCommand_HappinessPower:
; BUG: Return and Frustration deal no damage when the user's happiness is low or high, respectively (see docs/bugs_and_glitches.md)
push bc
ld hl, wBattleMonHappiness
ldh a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyMonHappiness
.ok
xor a
ldh [hMultiplicand + 0], a
ldh [hMultiplicand + 1], a
ld a, [hl]
ldh [hMultiplicand + 2], a
ld a, 10
ldh [hMultiplier], a
call Multiply
ld a, 25
ldh [hDivisor], a
ld b, 4
call Divide
ldh a, [hQuotient + 3]
ld d, a
pop bc
ret

View file

@ -0,0 +1,91 @@
DEF MAX_ROLLOUT_COUNT EQU 5
BattleCommand_CheckCurl:
ld de, wPlayerRolloutCount
ldh a, [hBattleTurn]
and a
jr z, .ok
ld de, wEnemyRolloutCount
.ok
ld a, BATTLE_VARS_SUBSTATUS1
call GetBattleVar
bit SUBSTATUS_ROLLOUT, a
jr z, .reset
ld b, doturn_command
jp SkipToBattleCommand
.reset
xor a
ld [de], a
ret
BattleCommand_RolloutPower:
ld a, BATTLE_VARS_STATUS
call GetBattleVar
and SLP_MASK
ret nz
ld hl, wPlayerRolloutCount
ldh a, [hBattleTurn]
and a
jr z, .got_rollout_count
ld hl, wEnemyRolloutCount
.got_rollout_count
ld a, [hl]
and a
jr nz, .skip_set_rampage
ld a, 1
ld [wSomeoneIsRampaging], a
.skip_set_rampage
ld a, [wAttackMissed]
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, wCurDamage + 1
sla [hl]
dec hl
rl [hl]
jr nc, .loop
ld a, $ff
ld [hli], a
ld [hl], a
.done_damage
ret

View file

@ -0,0 +1,21 @@
BattleCommand_Safeguard:
ld hl, wPlayerScreens
ld de, wPlayerSafeguardCount
ldh a, [hBattleTurn]
and a
jr z, .ok
ld hl, wEnemyScreens
ld de, wEnemySafeguardCount
.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

View file

@ -0,0 +1,16 @@
BattleCommand_StartSandstorm:
ld a, [wBattleWeather]
cp WEATHER_SANDSTORM
jr z, .failed
ld a, WEATHER_SANDSTORM
ld [wBattleWeather], a
ld a, 5
ld [wWeatherCount], a
call AnimateCurrentMove
ld hl, SandstormBrewedText
jp StdBattleTextbox
.failed
call AnimateFailedMove
jp PrintButItFailed

View file

@ -0,0 +1,29 @@
BattleCommand_Selfdestruct:
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 [wBattleAnimParam], 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

View file

@ -0,0 +1,121 @@
BattleCommand_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.
; BUG: A Transformed Pokémon can use Sketch and learn otherwise unobtainable moves (see docs/bugs_and_glitches.md)
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, wBattleMonMoves
ldh a, [hBattleTurn]
and a
jr z, .get_last_move
ld hl, wEnemyMonMoves
.get_last_move
ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
call GetBattleVar
ld [wNamedObjectIndex], a
ld b, a
; Fail if move is invalid or is Struggle.
and a
jr z, .fail
push bc
ld bc, STRUGGLE
call CompareMove
pop bc
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.
push hl
ld hl, SKETCH
call GetMoveIDFromIndex
pop hl
ld c, NUM_MOVES
.find_sketch
dec c
dec hl
cp [hl]
jr nz, .find_sketch
; 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
ld l, a
ld a, MOVE_PP
call GetMoveAttribute
pop hl
ld bc, wBattleMonPP - wBattleMonMoves
add hl, bc
ld [hl], a
pop bc
ldh 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

View file

@ -0,0 +1,141 @@
BattleCommand_SleepTalk:
call ClearLastMove
ld a, [wAttackMissed]
and a
jr nz, .fail
ldh a, [hBattleTurn]
and a
ld hl, wBattleMonMoves + 1
ld a, [wDisabledMove]
ld d, a
jr z, .got_moves
ld hl, wEnemyMonMoves + 1
ld a, [wEnemyDisabledMove]
ld d, a
.got_moves
ld a, BATTLE_VARS_STATUS
call GetBattleVar
and SLP_MASK
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, [wBattleAnimParam]
push af
call BattleCommand_LowerSub
pop af
ld [wBattleAnimParam], 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
ldh a, [hBattleTurn]
and a
ld a, [wDisabledMove]
jr z, .got_move_2
ld a, [wEnemyDisabledMove]
.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

View file

@ -0,0 +1,10 @@
BattleCommand_Snore:
ld a, BATTLE_VARS_STATUS
call GetBattleVar
and SLP_MASK
ret nz
call ResetDamage
ld a, $1
ld [wAttackMissed], a
call FailMove
jp EndMoveEffect

View file

@ -0,0 +1,24 @@
BattleCommand_Spikes:
ld hl, wEnemyScreens
ldh a, [hBattleTurn]
and a
jr z, .got_screens
ld hl, wPlayerScreens
.got_screens
; 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

View file

@ -0,0 +1,87 @@
BattleCommand_Spite:
ld a, [wAttackMissed]
and a
jp nz, .failed
ld bc, PARTYMON_STRUCT_LENGTH ; unused
ld hl, wEnemyMonMoves
ldh a, [hBattleTurn]
and a
jr z, .got_moves
ld hl, wBattleMonMoves
.got_moves
ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP
call GetBattleVar
and a
jr z, .failed
ld b, a
push bc
ld bc, STRUGGLE
call CompareMove
pop bc
jr z, .failed
ld c, -1
.loop
inc c
ld a, [hli]
cp b
jr nz, .loop
ld [wNamedObjectIndex], a
dec hl
ld b, 0
push bc
ld c, wBattleMonPP - wBattleMonMoves
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
ldh 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 [wTextDecimalByte], a
ld hl, SpiteEffectText
jp StdBattleTextbox
.failed
jp PrintDidntAffect2

View file

@ -0,0 +1,4 @@
BattleCommand_Splash:
call AnimateCurrentMove
farcall StubbedTrainerRankings_Splash
jp PrintNothingHappened

View file

@ -0,0 +1,86 @@
BattleCommand_Substitute:
call BattleCommand_MoveDelay
ld hl, wBattleMonMaxHP
ld de, wPlayerSubstituteHP
ldh a, [hBattleTurn]
and a
jr z, .got_hp
ld hl, wEnemyMonMaxHP
ld de, wEnemySubstituteHP
.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
ldh 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 [wBattleAnimParam], a
ld hl, SUBSTITUTE
call GetMoveIDFromIndex
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

View file

@ -0,0 +1,8 @@
BattleCommand_StartSun:
ld a, WEATHER_SUN
ld [wBattleWeather], a
ld a, 5
ld [wWeatherCount], a
call AnimateCurrentMove
ld hl, SunGotBrightText
jp StdBattleTextbox

View file

@ -0,0 +1,94 @@
BattleCommand_Teleport:
ld a, [wBattleType]
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
ldh a, [hBattleTurn]
and a
jr nz, .enemy_turn
; Can't teleport from a trainer battle
ld a, [wBattleMode]
dec a
jr nz, .failed
; b = player level
ld a, [wCurPartyLevel]
ld b, a
; If player level >= enemy level, Teleport will succeed
ld a, [wBattleMonLevel]
cp b
jr nc, .run_away
; c = player level + enemy level + 1
add b
ld c, a
inc c
; Generate a number less than c
.loop_player
call BattleRandom
cp c
jr nc, .loop_player
; b = enemy level / 4
srl b
srl b
; If the random number >= enemy level / 4, Teleport will succeed
cp b
jr nc, .run_away
.failed
call AnimateFailedMove
jp PrintButItFailed
.enemy_turn
; Can't teleport from a trainer battle
ld a, [wBattleMode]
dec a
jr nz, .failed
; b = enemy level
ld a, [wBattleMonLevel]
ld b, a
; If enemy level >= player level, Teleport will succeed
ld a, [wCurPartyLevel]
cp b
jr nc, .run_away
; c = enemy level + player level + 1
add b
ld c, a
inc c
; Generate a number less than c
.loop_enemy
; BUG: Wild Pokémon can always Teleport regardless of level difference (see docs/bugs_and_glitches.md)
call BattleRandom
cp c
jr nc, .loop_enemy
; b = player level / 4
srl b
srl b
cp b
jr nc, .run_away
.run_away
call UpdateBattleMonInParty
xor a
ld [wNumHits], a
inc a
ld [wForcedSwitch], a
ld [wBattleAnimParam], a
call SetBattleDraw
call BattleCommand_LowerSub
call LoadMoveAnim
ld c, 20
call DelayFrames
call SetBattleDraw
ld hl, FledFromBattleText
jp StdBattleTextbox

View file

@ -0,0 +1,110 @@
BattleCommand_Thief:
ldh 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 [wNamedObjectIndex], a
ld d, a
farcall ItemIsMail
ret c
ld a, [wEffectFailed]
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, [wNamedObjectIndex]
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 [wNamedObjectIndex], a
ld d, a
farcall ItemIsMail
ret c
ld a, [wEffectFailed]
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, [wNamedObjectIndex]
ld [hl], a
ld [de], a
.stole
call GetItemName
ld hl, StoleText
jp StdBattleTextbox
.playeritem
ld a, MON_ITEM
call BattlePartyAttr
ld d, h
ld e, l
ld hl, wBattleMonItem
ret
.enemyitem
ld a, MON_ITEM
call OTPartyAttr
ld d, h
ld e, l
ld hl, wEnemyMonItem
ret

View file

@ -0,0 +1,16 @@
BattleCommand_ThunderAccuracy:
ld a, BATTLE_VARS_MOVE_TYPE
call GetBattleVarAddr
inc hl
ld a, [wBattleWeather]
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

View file

@ -0,0 +1,156 @@
BattleCommand_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 a, $1
ld [wBattleAnimParam], 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 hl, SUBSTITUTE
call GetMoveIDFromIndex
call LoadAnim
.mimic_substitute
ld a, BATTLE_VARS_SUBSTATUS5
call GetBattleVarAddr
set SUBSTATUS_TRANSFORMED, [hl]
call ResetActorDisable
ld hl, wBattleMonSpecies
ld de, wEnemyMonSpecies
ldh a, [hBattleTurn]
and a
jr nz, .got_mon_species
ld hl, wEnemyMonSpecies
ld de, wBattleMonSpecies
xor a
ld [wCurMoveNum], a
.got_mon_species
push hl
ld a, [hli]
ld [de], a
inc hl
inc de
inc de
ld bc, NUM_MOVES
call CopyBytes
ldh 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, wBattleMonStats - wBattleMonPP
add hl, bc
push hl
ld h, d
ld l, e
add hl, bc
ld d, h
ld e, l
pop hl
ld bc, wBattleMonStructEnd - wBattleMonStats
call CopyBytes
; init the power points
ld bc, wBattleMonMoves - wBattleMonStructEnd
add hl, bc
push de
ld d, h
ld e, l
pop hl
ld bc, wBattleMonPP - wBattleMonStructEnd
add hl, bc
ld b, NUM_MOVES
.pp_loop
ld a, [de]
inc de
and a
jr z, .done_move
push bc
ld bc, SKETCH
call CompareMove
pop bc
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 [wNamedObjectIndex], a
call GetPokemonName
ld hl, wEnemyStats
ld de, wPlayerStats
ld bc, 2 * 5
call BattleSideCopy
ld hl, wEnemyStatLevels
ld de, wPlayerStatLevels
ld bc, 8
call BattleSideCopy
call _CheckBattleScene
jr c, .mimic_anims
ldh 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 a, $2
ld [wBattleAnimParam], a
pop af
jr z, .no_substitute
ld hl, SUBSTITUTE
call GetMoveIDFromIndex
call LoadAnim
.no_substitute
ld hl, TransformedText
jp StdBattleTextbox
BattleSideCopy:
; 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.
ldh a, [hBattleTurn]
and a
jr z, .copy
; Swap hl and de
push hl
ld h, d
ld l, e
pop de
.copy
jp CopyBytes

View file

@ -0,0 +1,30 @@
BattleCommand_TripleKick:
ld a, [wBattleAnimParam]
ld b, a
inc b
ld hl, wCurDamage + 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
BattleCommand_KickCounter:
ld hl, wBattleAnimParam
inc [hl]
ret