pokered/engine/battle/core.asm

8720 lines
190 KiB
NASM
Raw Normal View History

2014-05-22 22:13:20 +00:00
BattleCore:
; These are move effects (second value from the Moves table in bank $E).
2016-06-12 00:24:04 +00:00
ResidualEffects1:
; most non-side effects
2014-05-22 22:13:20 +00:00
db CONVERSION_EFFECT
db HAZE_EFFECT
db SWITCH_AND_TELEPORT_EFFECT
db MIST_EFFECT
db FOCUS_ENERGY_EFFECT
db CONFUSION_EFFECT
db HEAL_EFFECT
db TRANSFORM_EFFECT
db LIGHT_SCREEN_EFFECT
db REFLECT_EFFECT
db POISON_EFFECT
db PARALYZE_EFFECT
db SUBSTITUTE_EFFECT
db MIMIC_EFFECT
db LEECH_SEED_EFFECT
db SPLASH_EFFECT
db -1
2016-06-12 00:24:04 +00:00
SetDamageEffects:
2014-05-22 22:13:20 +00:00
; moves that do damage but not through normal calculations
; e.g., Super Fang, Psywave
db SUPER_FANG_EFFECT
db SPECIAL_DAMAGE_EFFECT
db -1
2016-06-12 00:24:04 +00:00
ResidualEffects2:
; non-side effects not included in ResidualEffects1
2015-01-04 16:47:21 +00:00
; stat-affecting moves, sleep-inflicting moves, and Bide
2014-05-22 22:13:20 +00:00
; e.g., Meditate, Bide, Hypnosis
db $01
db ATTACK_UP1_EFFECT
db DEFENSE_UP1_EFFECT
db SPEED_UP1_EFFECT
db SPECIAL_UP1_EFFECT
db ACCURACY_UP1_EFFECT
db EVASION_UP1_EFFECT
db ATTACK_DOWN1_EFFECT
db DEFENSE_DOWN1_EFFECT
db SPEED_DOWN1_EFFECT
db SPECIAL_DOWN1_EFFECT
db ACCURACY_DOWN1_EFFECT
db EVASION_DOWN1_EFFECT
db BIDE_EFFECT
db SLEEP_EFFECT
db ATTACK_UP2_EFFECT
db DEFENSE_UP2_EFFECT
db SPEED_UP2_EFFECT
db SPECIAL_UP2_EFFECT
db ACCURACY_UP2_EFFECT
db EVASION_UP2_EFFECT
db ATTACK_DOWN2_EFFECT
db DEFENSE_DOWN2_EFFECT
db SPEED_DOWN2_EFFECT
db SPECIAL_DOWN2_EFFECT
db ACCURACY_DOWN2_EFFECT
db EVASION_DOWN2_EFFECT
db -1
2016-06-12 00:24:04 +00:00
AlwaysHappenSideEffects:
2014-05-22 22:13:20 +00:00
; Attacks that aren't finished after they faint the opponent.
db DRAIN_HP_EFFECT
db EXPLODE_EFFECT
db DREAM_EATER_EFFECT
db PAY_DAY_EFFECT
db TWO_TO_FIVE_ATTACKS_EFFECT
db $1E
db ATTACK_TWICE_EFFECT
db RECOIL_EFFECT
db TWINEEDLE_EFFECT
db RAGE_EFFECT
db -1
2016-06-12 00:24:04 +00:00
SpecialEffects:
2015-01-04 16:47:21 +00:00
; Effects from arrays 2, 4, and 5B, minus Twineedle and Rage.
2015-01-23 03:05:13 +00:00
; Includes all effects that do not need to be called at the end of
2015-01-04 16:47:21 +00:00
; ExecutePlayerMove (or ExecuteEnemyMove), because they have already been handled
2014-05-22 22:13:20 +00:00
db DRAIN_HP_EFFECT
db EXPLODE_EFFECT
db DREAM_EATER_EFFECT
db PAY_DAY_EFFECT
db SWIFT_EFFECT
db TWO_TO_FIVE_ATTACKS_EFFECT
db $1E
db CHARGE_EFFECT
db SUPER_FANG_EFFECT
db SPECIAL_DAMAGE_EFFECT
db FLY_EFFECT
db ATTACK_TWICE_EFFECT
db JUMP_KICK_EFFECT
db RECOIL_EFFECT
; fallthrough to Next EffectsArray
2016-06-12 00:24:04 +00:00
SpecialEffectsCont:
2015-01-04 16:47:21 +00:00
; damaging moves whose effect is executed prior to damage calculation
2014-05-22 22:13:20 +00:00
db THRASH_PETAL_DANCE_EFFECT
db TRAPPING_EFFECT
db -1
2016-06-12 00:24:04 +00:00
SlidePlayerAndEnemySilhouettesOnScreen:
2014-08-09 05:39:13 +00:00
call LoadPlayerBackPic
2015-02-07 20:27:36 +00:00
ld a, MESSAGE_BOX ; the usual text box at the bottom of the screen
2015-02-07 10:43:08 +00:00
ld [wTextBoxID], a
2014-05-22 22:13:20 +00:00
call DisplayTextBoxID
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
2015-08-05 21:20:29 +00:00
lb bc, 3, 7
2014-05-22 22:13:20 +00:00
call ClearScreenArea
call DisableLCD
call LoadFontTilePatterns
2014-08-09 05:39:13 +00:00
call LoadHudAndHpBarAndStatusTilePatterns
2014-05-29 08:31:46 +00:00
ld hl, vBGMap0
2014-05-22 22:13:20 +00:00
ld bc, $400
2014-08-09 05:39:13 +00:00
.clearBackgroundLoop
2015-08-05 21:20:29 +00:00
ld a, " "
2014-05-22 22:13:20 +00:00
ld [hli], a
dec bc
ld a, b
or c
2014-08-09 05:39:13 +00:00
jr nz, .clearBackgroundLoop
; copy the work RAM tile map to VRAM
2015-07-18 20:52:03 +00:00
coord hl, 0, 0
2014-05-29 08:31:46 +00:00
ld de, vBGMap0
2014-08-09 05:39:13 +00:00
ld b, 18 ; number of rows
.copyRowLoop
ld c, 20 ; number of columns
.copyColumnLoop
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [de], a
inc e
dec c
2014-08-09 05:39:13 +00:00
jr nz, .copyColumnLoop
ld a, 12 ; number of off screen tiles to the right of screen in VRAM
add e ; skip the off screen tiles
2014-05-22 22:13:20 +00:00
ld e, a
2014-08-09 05:39:13 +00:00
jr nc, .noCarry
2014-05-22 22:13:20 +00:00
inc d
2014-08-09 05:39:13 +00:00
.noCarry
2014-05-22 22:13:20 +00:00
dec b
2014-08-09 05:39:13 +00:00
jr nz, .copyRowLoop
2014-05-22 22:13:20 +00:00
call EnableLCD
ld a, $90
2014-09-23 22:02:03 +00:00
ld [hWY], a
2014-08-09 05:39:13 +00:00
ld [rWY], a
2014-05-22 22:13:20 +00:00
xor a
2014-09-14 18:29:18 +00:00
ld [hTilesetType], a
2014-09-23 22:02:03 +00:00
ld [hSCY], a
2014-05-22 22:13:20 +00:00
dec a
2014-09-13 07:50:56 +00:00
ld [wUpdateSpritesEnabled], a
2014-05-22 22:13:20 +00:00
call Delay3
xor a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-05-22 22:13:20 +00:00
ld b, $70
ld c, $90
ld a, c
2014-09-23 22:02:03 +00:00
ld [hSCX], a
2014-05-22 22:13:20 +00:00
call DelayFrame
2014-08-09 05:39:13 +00:00
ld a, %11100100 ; inverted palette for silhouette effect
ld [rBGP], a
ld [rOBP0], a
ld [rOBP1], a
.slideSilhouettesLoop ; slide silhouettes of the player's pic and the enemy's pic onto the screen
2014-05-22 22:13:20 +00:00
ld h, b
ld l, $40
2014-08-09 05:39:13 +00:00
call SetScrollXForSlidingPlayerBodyLeft ; begin background scrolling on line $40
2014-05-22 22:13:20 +00:00
inc b
inc b
ld h, $0
ld l, $60
2014-08-09 05:39:13 +00:00
call SetScrollXForSlidingPlayerBodyLeft ; end background scrolling on line $60
call SlidePlayerHeadLeft
2014-05-22 22:13:20 +00:00
ld a, c
2014-09-23 22:02:03 +00:00
ld [hSCX], a
2014-05-22 22:13:20 +00:00
dec c
dec c
2014-08-09 05:39:13 +00:00
jr nz, .slideSilhouettesLoop
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-05-22 22:13:20 +00:00
ld a, $31
2015-07-24 03:48:35 +00:00
ld [hStartTileID], a
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
predef CopyUncompressedPicToTilemap
2014-05-22 22:13:20 +00:00
xor a
2014-09-23 22:02:03 +00:00
ld [hWY], a
2014-08-09 05:39:13 +00:00
ld [rWY], a
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-05-22 22:13:20 +00:00
call Delay3
2015-08-12 09:16:56 +00:00
ld b, SET_PAL_BATTLE
call RunPaletteCommand
2014-05-23 22:34:35 +00:00
call HideSprites
2015-07-19 18:56:13 +00:00
jpab PrintBeginningBattleText
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
; when a battle is starting, silhouettes of the player's pic and the enemy's pic are slid onto the screen
; the lower of the player's pic (his body) is part of the background, but his head is a sprite
; the reason for this is that it shares Y coordinates with the lower part of the enemy pic, so background scrolling wouldn't work for both pics
; instead, the enemy pic is part of the background and uses the scroll register, while the player's head is a sprite and is slid by changing its X coordinates in a loop
2016-06-12 00:24:04 +00:00
SlidePlayerHeadLeft:
2014-05-22 22:13:20 +00:00
push bc
ld hl, wOAMBuffer + $01
2014-08-09 05:39:13 +00:00
ld c, $15 ; number of OAM entries
ld de, $4 ; size of OAM entry
.loop
dec [hl] ; decrement X
dec [hl] ; decrement X
add hl, de ; next OAM entry
2014-05-22 22:13:20 +00:00
dec c
2014-08-09 05:39:13 +00:00
jr nz, .loop
2014-05-22 22:13:20 +00:00
pop bc
ret
2016-06-12 00:24:04 +00:00
SetScrollXForSlidingPlayerBodyLeft:
2014-08-09 05:39:13 +00:00
ld a, [rLY]
2014-05-22 22:13:20 +00:00
cp l
2014-08-09 05:39:13 +00:00
jr nz, SetScrollXForSlidingPlayerBodyLeft
2014-05-22 22:13:20 +00:00
ld a, h
2014-08-09 05:39:13 +00:00
ld [rSCX], a
.loop
ld a, [rLY]
2014-05-22 22:13:20 +00:00
cp h
2014-08-09 05:39:13 +00:00
jr z, .loop
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
StartBattle:
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wPartyGainExpFlags], a
ld [wPartyFoughtCurrentEnemyFlags], a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-05-22 22:13:20 +00:00
inc a
2015-07-25 03:27:59 +00:00
ld [wFirstMonsNotOutYet], a
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMon1HP
ld bc, wEnemyMon2 - wEnemyMon1 - 1
2014-05-22 22:13:20 +00:00
ld d, $3
2014-08-09 05:39:13 +00:00
.findFirstAliveEnemyMonLoop
2014-05-22 22:13:20 +00:00
inc d
ld a, [hli]
or [hl]
2014-08-09 05:39:13 +00:00
jr nz, .foundFirstAliveEnemyMon
2014-05-22 22:13:20 +00:00
add hl, bc
2014-08-09 05:39:13 +00:00
jr .findFirstAliveEnemyMonLoop
.foundFirstAliveEnemyMon
2014-05-22 22:13:20 +00:00
ld a, d
2015-02-07 10:43:08 +00:00
ld [wSerialExchangeNybbleReceiveData], a
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-08-09 05:39:13 +00:00
dec a ; is it a trainer battle?
call nz, EnemySendOutFirstMon ; if it is a trainer battle, send out enemy mon
ld c, 40
2014-05-22 22:13:20 +00:00
call DelayFrames
call SaveScreenTilesToBuffer1
2014-08-09 05:39:13 +00:00
.checkAnyPartyAlive
call AnyPartyAlive
2014-05-22 22:13:20 +00:00
ld a, d
and a
2014-08-09 05:39:13 +00:00
jp z, HandlePlayerBlackOut ; jump if no mon is alive
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2014-08-09 05:39:13 +00:00
and a ; is it a normal battle?
jp z, .playerSendOutFirstMon ; if so, send out player mon
; safari zone battle
.displaySafariZoneBattleMenu
call DisplayBattleMenu
ret c ; return if the player ran from battle
2015-07-15 06:16:06 +00:00
ld a, [wActionResultOrTookBattleTurn]
2014-08-09 05:39:13 +00:00
and a ; was the item used successfully?
jr z, .displaySafariZoneBattleMenu ; if not, display the menu again; XXX does this ever jump?
2015-08-31 02:38:41 +00:00
ld a, [wNumSafariBalls]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr nz, .notOutOfSafariBalls
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2014-08-09 05:39:13 +00:00
ld hl, .outOfSafariBallsText
2014-05-22 22:13:20 +00:00
jp PrintText
2014-08-09 05:39:13 +00:00
.notOutOfSafariBalls
2014-05-22 22:13:20 +00:00
callab PrintSafariZoneBattleText
ld a, [wEnemyMonSpeed + 1]
2014-05-22 22:13:20 +00:00
add a
2014-08-09 05:39:13 +00:00
ld b, a ; init b (which is later compared with random value) to (enemy speed % 256) * 2
jp c, EnemyRan ; if (enemy speed % 256) > 127, the enemy runs
ld a, [wSafariBaitFactor]
and a ; is bait factor 0?
jr z, .checkEscapeFactor
; bait factor is not 0
; divide b by 4 (making the mon less likely to run)
2014-05-22 22:13:20 +00:00
srl b
srl b
2014-08-09 05:39:13 +00:00
.checkEscapeFactor
ld a, [wSafariEscapeFactor]
and a ; is escape factor 0?
jr z, .compareWithRandomValue
; escape factor is not 0
; multiply b by 2 (making the mon more likely to run)
2014-05-22 22:13:20 +00:00
sla b
2014-08-09 05:39:13 +00:00
jr nc, .compareWithRandomValue
; cap b at 255
2014-05-22 22:13:20 +00:00
ld b, $ff
2014-08-09 05:39:13 +00:00
.compareWithRandomValue
call Random
2014-05-22 22:13:20 +00:00
cp b
2014-08-09 05:39:13 +00:00
jr nc, .checkAnyPartyAlive
jr EnemyRan ; if b was greater than the random value, the enemy runs
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
.outOfSafariBallsText
2014-05-22 22:13:20 +00:00
TX_FAR _OutOfSafariBallsText
db "@"
2014-08-09 05:39:13 +00:00
.playerSendOutFirstMon
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wWhichPokemon], a
.findFirstAliveMonLoop
call HasMonFainted
jr nz, .foundFirstAliveMon
; fainted, go to the next one
ld hl, wWhichPokemon
2014-05-22 22:13:20 +00:00
inc [hl]
2014-08-09 05:39:13 +00:00
jr .findFirstAliveMonLoop
.foundFirstAliveMon
ld a, [wWhichPokemon]
ld [wPlayerMonNumber], a
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld hl, wPartySpecies - 1
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
2014-08-09 05:39:13 +00:00
ld a, [hl] ; species
ld [wcf91], a
ld [wBattleMonSpecies2], a
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
2014-05-22 22:13:20 +00:00
ld a, $9
2014-08-09 05:39:13 +00:00
call SlideTrainerPicOffScreen
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
2014-05-22 22:13:20 +00:00
ld c, a
2015-07-20 03:45:34 +00:00
ld b, FLAG_SET
2014-05-22 22:13:20 +00:00
push bc
2014-08-09 05:39:13 +00:00
ld hl, wPartyGainExpFlags
predef FlagActionPredef
2014-08-09 05:39:13 +00:00
ld hl, wPartyFoughtCurrentEnemyFlags
2014-05-22 22:13:20 +00:00
pop bc
predef FlagActionPredef
2014-08-09 05:39:13 +00:00
call LoadBattleMonFromParty
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2014-08-09 05:39:13 +00:00
call SendOutMon
2014-05-22 22:13:20 +00:00
jr MainInBattleLoop
2014-08-09 05:39:13 +00:00
; wild mon or link battle enemy ran from battle
2016-06-12 00:24:04 +00:00
EnemyRan:
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
ld hl, WildRanText
2014-08-09 05:39:13 +00:00
jr nz, .printText
; link battle
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wBattleResult], a
2014-05-22 22:13:20 +00:00
ld hl, EnemyRanText
2014-08-09 05:39:13 +00:00
.printText
2014-05-22 22:13:20 +00:00
call PrintText
2015-07-22 01:58:19 +00:00
ld a, SFX_RUN
2014-05-22 22:13:20 +00:00
call PlaySoundWaitForCurrent
xor a
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2015-07-24 21:39:45 +00:00
jpab AnimationSlideEnemyMonOff
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
WildRanText:
2014-05-22 22:13:20 +00:00
TX_FAR _WildRanText
db "@"
2016-06-12 00:24:04 +00:00
EnemyRanText:
2014-05-22 22:13:20 +00:00
TX_FAR _EnemyRanText
db "@"
2016-06-12 00:24:04 +00:00
MainInBattleLoop:
2014-05-22 22:13:20 +00:00
call ReadPlayerMonCurHPAndStatus
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
or [hl] ; is battle mon HP 0?
jp z, HandlePlayerMonFainted ; if battle mon HP is 0, jump
ld hl, wEnemyMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
or [hl] ; is enemy mon HP 0?
jp z, HandleEnemyMonFainted ; if enemy mon HP is 0, jump
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
xor a
2015-07-25 03:27:59 +00:00
ld [wFirstMonsNotOutYet], a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus2]
2017-12-29 23:59:48 +00:00
and (1 << NEEDS_TO_RECHARGE) | (1 << USING_RAGE) ; check if the player is using Rage or needs to recharge
2014-08-09 05:39:13 +00:00
jr nz, .selectEnemyMove
; the player is not using Rage and doesn't need to recharge
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res FLINCHED, [hl] ; reset flinch bit
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2017-12-29 23:59:48 +00:00
res FLINCHED, [hl] ; reset flinch bit
2014-05-22 22:13:20 +00:00
ld a, [hl]
2017-12-29 23:59:48 +00:00
and (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) ; check if the player is thrashing about or charging for an attack
2014-08-09 05:39:13 +00:00
jr nz, .selectEnemyMove ; if so, jump
; the player is neither thrashing about nor charging for an attack
call DisplayBattleMenu ; show battle menu
ret c ; return if player ran from battle
ld a, [wEscapedFromBattle]
and a
ret nz ; return if pokedoll was used to escape from battle
ld a, [wBattleMonStatus]
2014-08-09 05:39:13 +00:00
and (1 << FRZ) | SLP ; is mon frozen or asleep?
jr nz, .selectEnemyMove ; if so, jump
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus1]
2017-12-29 23:59:48 +00:00
and (1 << STORING_ENERGY) | (1 << USING_TRAPPING_MOVE) ; check player is using Bide or using a multi-turn attack like wrap
2014-08-09 05:39:13 +00:00
jr nz, .selectEnemyMove ; if so, jump
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus1]
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, a ; check if enemy is using a multi-turn attack like wrap
2014-08-09 05:39:13 +00:00
jr z, .selectPlayerMove ; if not, jump
2017-06-24 20:01:43 +00:00
; enemy is using a multi-turn attack like wrap, so player is trapped and cannot execute a move
2014-05-22 22:13:20 +00:00
ld a, $ff
ld [wPlayerSelectedMove], a
2014-08-09 05:39:13 +00:00
jr .selectEnemyMove
.selectPlayerMove
2015-07-15 06:16:06 +00:00
ld a, [wActionResultOrTookBattleTurn]
and a ; has the player already used the turn (e.g. by using an item, trying to run or switching pokemon)
2014-08-09 05:39:13 +00:00
jr nz, .selectEnemyMove
ld [wMoveMenuType], a
2014-05-22 22:13:20 +00:00
inc a
2015-08-31 02:38:41 +00:00
ld [wAnimationID], a
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wMenuItemToSwap], a
2014-05-22 22:13:20 +00:00
call MoveSelectionMenu
push af
call LoadScreenTilesFromBuffer1
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
2014-05-22 22:13:20 +00:00
pop af
2014-08-09 05:39:13 +00:00
jr nz, MainInBattleLoop ; if the player didn't select a move, jump
.selectEnemyMove
2014-05-22 22:13:20 +00:00
call SelectEnemyMove
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
jr nz, .noLinkBattle
2014-08-09 05:39:13 +00:00
; link battle
2015-02-07 10:43:08 +00:00
ld a, [wSerialExchangeNybbleReceiveData]
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_RUN
2014-08-09 05:39:13 +00:00
jp z, EnemyRan
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_STRUGGLE
2014-05-22 22:13:20 +00:00
jr z, .noLinkBattle
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_NO_ACTION
2014-05-22 22:13:20 +00:00
jr z, .noLinkBattle
2016-10-29 08:44:13 +00:00
sub 4
2014-05-22 22:13:20 +00:00
jr c, .noLinkBattle
2014-08-09 05:39:13 +00:00
; the link battle enemy has switched mons
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus1]
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, a ; check if using multi-turn move like Wrap
2016-06-12 04:30:05 +00:00
jr z, .specialMoveNotUsed
ld a, [wPlayerMoveListIndex]
ld hl, wBattleMonMoves
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, [hl]
cp METRONOME ; a MIRROR MOVE check is missing, might lead to a desync in link battles
; when combined with multi-turn moves
2016-06-12 04:30:05 +00:00
jr nz, .specialMoveNotUsed
2014-05-22 22:13:20 +00:00
ld [wPlayerSelectedMove], a
2016-06-12 04:30:05 +00:00
.specialMoveNotUsed
2014-08-09 05:39:13 +00:00
callab SwitchEnemyMon
2014-05-22 22:13:20 +00:00
.noLinkBattle
ld a, [wPlayerSelectedMove]
cp QUICK_ATTACK
jr nz, .playerDidNotUseQuickAttack
ld a, [wEnemySelectedMove]
cp QUICK_ATTACK
2014-08-09 05:39:13 +00:00
jr z, .compareSpeed ; if both used Quick Attack
jp .playerMovesFirst ; if player used Quick Attack and enemy didn't
2014-05-22 22:13:20 +00:00
.playerDidNotUseQuickAttack
ld a, [wEnemySelectedMove]
cp QUICK_ATTACK
2014-08-09 05:39:13 +00:00
jr z, .enemyMovesFirst ; if enemy used Quick Attack and player didn't
2014-05-22 22:13:20 +00:00
ld a, [wPlayerSelectedMove]
cp COUNTER
jr nz, .playerDidNotUseCounter
ld a, [wEnemySelectedMove]
cp COUNTER
2014-08-09 05:39:13 +00:00
jr z, .compareSpeed ; if both used Counter
jr .enemyMovesFirst ; if player used Counter and enemy didn't
2014-05-22 22:13:20 +00:00
.playerDidNotUseCounter
ld a, [wEnemySelectedMove]
cp COUNTER
2014-08-09 05:39:13 +00:00
jr z, .playerMovesFirst ; if enemy used Counter and player didn't
2014-05-22 22:13:20 +00:00
.compareSpeed
ld de, wBattleMonSpeed ; player speed value
ld hl, wEnemyMonSpeed ; enemy speed value
2014-05-22 22:13:20 +00:00
ld c, $2
call StringCmp ; compare speed values
jr z, .speedEqual
2014-08-09 05:39:13 +00:00
jr nc, .playerMovesFirst ; if player is faster
jr .enemyMovesFirst ; if enemy is faster
2015-01-04 16:47:21 +00:00
.speedEqual ; 50/50 chance for both players
2016-10-29 17:32:03 +00:00
ld a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
2014-05-22 22:13:20 +00:00
jr z, .invertOutcome
call BattleRandom
2014-05-22 22:13:20 +00:00
cp $80
jr c, .playerMovesFirst
jr .enemyMovesFirst
.invertOutcome
call BattleRandom
2014-05-22 22:13:20 +00:00
cp $80
jr c, .enemyMovesFirst
jr .playerMovesFirst
.enemyMovesFirst
ld a, $1
ld [H_WHOSETURN], a
callab TrainerAI
jr c, .AIActionUsedEnemyFirst
2014-08-09 05:39:13 +00:00
call ExecuteEnemyMove
ld a, [wEscapedFromBattle]
and a ; was Teleport, Road, or Whirlwind used to escape from battle?
ret nz ; if so, return
2014-05-22 22:13:20 +00:00
ld a, b
and a
2015-01-23 03:05:13 +00:00
jp z, HandlePlayerMonFainted
2014-05-22 22:13:20 +00:00
.AIActionUsedEnemyFirst
call HandlePoisonBurnLeechSeed
jp z, HandleEnemyMonFainted
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
call ExecutePlayerMove
ld a, [wEscapedFromBattle]
and a ; was Teleport, Road, or Whirlwind used to escape from battle?
ret nz ; if so, return
2014-05-22 22:13:20 +00:00
ld a, b
and a
jp z, HandleEnemyMonFainted
call HandlePoisonBurnLeechSeed
jp z, HandlePlayerMonFainted
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
call CheckNumAttacksLeft
2014-05-22 22:13:20 +00:00
jp MainInBattleLoop
.playerMovesFirst
2014-08-09 05:39:13 +00:00
call ExecutePlayerMove
ld a, [wEscapedFromBattle]
and a ; was Teleport, Road, or Whirlwind used to escape from battle?
ret nz ; if so, return
2014-05-22 22:13:20 +00:00
ld a, b
and a
jp z, HandleEnemyMonFainted
call HandlePoisonBurnLeechSeed
jp z, HandlePlayerMonFainted
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
2014-05-22 22:13:20 +00:00
ld a, $1
ld [H_WHOSETURN], a
callab TrainerAI
jr c, .AIActionUsedPlayerFirst
2014-08-09 05:39:13 +00:00
call ExecuteEnemyMove
ld a, [wEscapedFromBattle]
and a ; was Teleport, Road, or Whirlwind used to escape from battle?
ret nz ; if so, return
2014-05-22 22:13:20 +00:00
ld a, b
and a
jp z, HandlePlayerMonFainted
.AIActionUsedPlayerFirst
call HandlePoisonBurnLeechSeed
jp z, HandleEnemyMonFainted
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
call CheckNumAttacksLeft
2014-05-22 22:13:20 +00:00
jp MainInBattleLoop
2016-06-12 00:24:04 +00:00
HandlePoisonBurnLeechSeed:
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonHP
ld de, wBattleMonStatus
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .playersTurn
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonHP
ld de, wEnemyMonStatus
2014-05-22 22:13:20 +00:00
.playersTurn
ld a, [de]
and (1 << BRN) | (1 << PSN)
jr z, .notBurnedOrPoisoned
push hl
ld hl, HurtByPoisonText
ld a, [de]
and 1 << BRN
jr z, .poisoned
ld hl, HurtByBurnText
.poisoned
call PrintText
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
ld a, BURN_PSN_ANIM
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation ; play burn/poison animation
pop hl
call HandlePoisonBurnLeechSeed_DecreaseOwnHP
.notBurnedOrPoisoned
2015-08-31 02:38:41 +00:00
ld de, wPlayerBattleStatus2
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .playersTurn2
2015-08-31 02:38:41 +00:00
ld de, wEnemyBattleStatus2
2014-05-22 22:13:20 +00:00
.playersTurn2
ld a, [de]
add a
jr nc, .notLeechSeeded
push hl
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
push af
xor $1
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
ld a, ABSORB
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation ; play leech seed animation (from opposing mon)
pop af
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
pop hl
call HandlePoisonBurnLeechSeed_DecreaseOwnHP
call HandlePoisonBurnLeechSeed_IncreaseEnemyHP
push hl
ld hl, HurtByLeechSeedText
call PrintText
pop hl
.notLeechSeeded
ld a, [hli]
or [hl]
ret nz ; test if fainted
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
ld c, 20
2014-05-22 22:13:20 +00:00
call DelayFrames
xor a
ret
2016-06-12 00:24:04 +00:00
HurtByPoisonText:
2014-05-22 22:13:20 +00:00
TX_FAR _HurtByPoisonText
db "@"
2016-06-12 00:24:04 +00:00
HurtByBurnText:
2014-05-22 22:13:20 +00:00
TX_FAR _HurtByBurnText
db "@"
2016-06-12 00:24:04 +00:00
HurtByLeechSeedText:
2014-05-22 22:13:20 +00:00
TX_FAR _HurtByLeechSeedText
db "@"
; decreases the mon's current HP by 1/16 of the Max HP (multiplied by number of toxic ticks if active)
; note that the toxic ticks are considered even if the damage is not poison (hence the Leech Seed glitch)
; hl: HP pointer
; bc (out): total damage
2016-06-12 00:24:04 +00:00
HandlePoisonBurnLeechSeed_DecreaseOwnHP:
2014-05-22 22:13:20 +00:00
push hl
push hl
ld bc, $e ; skip to max HP
add hl, bc
ld a, [hli] ; load max HP
ld [wHPBarMaxHP+1], a
ld b, a
ld a, [hl]
ld [wHPBarMaxHP], a
ld c, a
srl b
rr c
srl b
rr c
srl c
srl c ; c = max HP/16 (assumption: HP < 1024)
ld a, c
and a
jr nz, .nonZeroDamage
inc c ; damage is at least 1
.nonZeroDamage
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus3
ld de, wPlayerToxicCounter
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .playersTurn
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus3
2016-06-12 04:30:05 +00:00
ld de, wEnemyToxicCounter
2014-05-22 22:13:20 +00:00
.playersTurn
2017-12-29 23:59:48 +00:00
bit BADLY_POISONED, [hl]
2014-05-22 22:13:20 +00:00
jr z, .noToxic
ld a, [de] ; increment toxic counter
inc a
ld [de], a
ld hl, $0000
.toxicTicksLoop
add hl, bc
dec a
jr nz, .toxicTicksLoop
ld b, h ; bc = damage * toxic counter
ld c, l
.noToxic
pop hl
inc hl
ld a, [hl] ; subtract total damage from current HP
ld [wHPBarOldHP], a
sub c
ld [hld], a
ld [wHPBarNewHP], a
ld a, [hl]
ld [wHPBarOldHP+1], a
sbc b
ld [hl], a
ld [wHPBarNewHP+1], a
jr nc, .noOverkill
xor a ; overkill: zero HP
ld [hli], a
ld [hl], a
ld [wHPBarNewHP], a
ld [wHPBarNewHP+1], a
.noOverkill
call UpdateCurMonHPBar
pop hl
ret
; adds bc to enemy HP
2017-06-24 20:01:43 +00:00
; bc isn't updated if HP subtracted was capped to prevent overkill
2016-06-12 00:24:04 +00:00
HandlePoisonBurnLeechSeed_IncreaseEnemyHP:
2014-05-22 22:13:20 +00:00
push hl
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonMaxHP
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .playersTurn
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonMaxHP
2014-05-22 22:13:20 +00:00
.playersTurn
ld a, [hli]
ld [wHPBarMaxHP+1], a
ld a, [hl]
ld [wHPBarMaxHP], a
2015-08-05 21:20:29 +00:00
ld de, wBattleMonHP - wBattleMonMaxHP
add hl, de ; skip back from max hp to current hp
2014-05-22 22:13:20 +00:00
ld a, [hl]
ld [wHPBarOldHP], a ; add bc to current HP
add c
ld [hld], a
ld [wHPBarNewHP], a
ld a, [hl]
ld [wHPBarOldHP+1], a
adc b
ld [hli], a
ld [wHPBarNewHP+1], a
ld a, [wHPBarMaxHP]
ld c, a
ld a, [hld]
sub c
ld a, [wHPBarMaxHP+1]
ld b, a
ld a, [hl]
sbc b
jr c, .noOverfullHeal
ld a, b ; overfull heal, set HP to max HP
ld [hli], a
ld [wHPBarNewHP+1], a
ld a, c
ld [hl], a
ld [wHPBarNewHP], a
.noOverfullHeal
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
xor $1
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
call UpdateCurMonHPBar
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
xor $1
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
pop hl
ret
2016-06-12 00:24:04 +00:00
UpdateCurMonHPBar:
2015-07-18 20:52:03 +00:00
coord hl, 10, 9 ; tile pointer to player HP bar
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld a, $1
jr z, .playersTurn
2015-07-18 20:52:03 +00:00
coord hl, 2, 2 ; tile pointer to enemy HP bar
2014-05-22 22:13:20 +00:00
xor a
.playersTurn
push bc
2015-02-08 06:18:42 +00:00
ld [wHPBarType], a
predef UpdateHPBar2
2014-05-22 22:13:20 +00:00
pop bc
ret
2016-06-12 00:24:04 +00:00
CheckNumAttacksLeft:
2014-08-09 05:39:13 +00:00
ld a, [wPlayerNumAttacksLeft]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr nz, .checkEnemy
; player has 0 attacks left
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2017-12-29 23:59:48 +00:00
res USING_TRAPPING_MOVE, [hl] ; player not using multi-turn attack like wrap any more
2014-08-09 05:39:13 +00:00
.checkEnemy
ld a, [wEnemyNumAttacksLeft]
2014-05-22 22:13:20 +00:00
and a
ret nz
2014-08-09 05:39:13 +00:00
; enemy has 0 attacks left
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res USING_TRAPPING_MOVE, [hl] ; enemy not using multi-turn attack like wrap any more
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
HandleEnemyMonFainted:
2014-05-22 22:13:20 +00:00
xor a
2015-08-14 07:36:06 +00:00
ld [wInHandlePlayerMonFainted], a
2014-05-22 22:13:20 +00:00
call FaintEnemyPokemon
call AnyPartyAlive
2014-05-22 22:13:20 +00:00
ld a, d
and a
2014-08-09 05:39:13 +00:00
jp z, HandlePlayerBlackOut ; if no party mons are alive, the player blacks out
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
or [hl] ; is battle mon HP zero?
call nz, DrawPlayerHUDAndHPBar ; if battle mon HP is not zero, draw player HD and HP bar
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
ret z ; return if it's a wild battle
2014-05-22 22:13:20 +00:00
call AnyEnemyPokemonAliveCheck
jp z, TrainerBattleVictory
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
or [hl] ; does battle mon have 0 HP?
jr nz, .skipReplacingBattleMon ; if not, skip replacing battle mon
call DoUseNextMonDialogue ; this call is useless in a trainer battle. it shouldn't be here
2014-05-22 22:13:20 +00:00
ret c
2014-08-09 05:39:13 +00:00
call ChooseNextMon
.skipReplacingBattleMon
2014-05-22 22:13:20 +00:00
ld a, $1
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-08-09 05:39:13 +00:00
call ReplaceFaintedEnemyMon
jp z, EnemyRan
2014-05-22 22:13:20 +00:00
xor a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-05-22 22:13:20 +00:00
jp MainInBattleLoop
FaintEnemyPokemon:
2014-05-22 22:13:20 +00:00
call ReadPlayerMonCurHPAndStatus
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
jr z, .wild
ld a, [wEnemyMonPartyPos]
ld hl, wEnemyMon1HP
2014-08-09 05:39:13 +00:00
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
xor a
ld [hli], a
ld [hl], a
.wild
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2017-12-29 23:59:48 +00:00
res ATTACKING_MULTIPLE_TIMES, [hl]
2015-08-07 06:53:23 +00:00
; Bug. This only zeroes the high byte of the player's accumulated damage,
; setting the accumulated damage to itself mod 256 instead of 0 as was probably
; intended. That alone is problematic, but this mistake has another more severe
; effect. This function's counterpart for when the player mon faints,
; RemoveFaintedPlayerMon, zeroes both the high byte and the low byte. In a link
; battle, the other player's Game Boy will call that function in response to
; the enemy mon (the player mon from the other side's perspective) fainting,
; and the states of the two Game Boys will go out of sync unless the damage
; was congruent to 0 modulo 256.
2014-05-22 22:13:20 +00:00
xor a
2015-08-07 06:53:23 +00:00
ld [wPlayerBideAccumulatedDamage], a
2015-02-08 09:44:41 +00:00
ld hl, wEnemyStatsToDouble ; clear enemy statuses
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
2015-08-31 02:38:41 +00:00
ld [wEnemyDisabledMove], a
ld [wEnemyDisabledMoveNumber], a
2015-07-12 22:51:04 +00:00
ld [wEnemyMonMinimized], a
ld hl, wPlayerUsedMove
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hl], a
2015-07-18 20:52:03 +00:00
coord hl, 12, 5
coord de, 12, 6
2014-08-09 05:39:13 +00:00
call SlideDownFaintedMonPic
2015-07-18 20:52:03 +00:00
coord hl, 0, 0
2015-08-05 21:20:29 +00:00
lb bc, 4, 11
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
jr z, .wild_win
xor a
2015-08-09 05:32:44 +00:00
ld [wFrequencyModifier], a
ld [wTempoModifier], a
2015-07-22 01:58:19 +00:00
ld a, SFX_FAINT_FALL
2014-05-22 22:13:20 +00:00
call PlaySoundWaitForCurrent
.sfxwait
ld a, [wChannelSoundIDs + Ch5]
2015-07-22 01:58:19 +00:00
cp SFX_FAINT_FALL
2014-05-22 22:13:20 +00:00
jr z, .sfxwait
2015-07-22 01:58:19 +00:00
ld a, SFX_FAINT_THUD
2014-05-22 22:13:20 +00:00
call PlaySound
call WaitForSoundToFinish
jr .sfxplayed
.wild_win
2015-03-31 18:50:49 +00:00
call EndLowHealthAlarm
2014-05-22 22:13:20 +00:00
ld a, MUSIC_DEFEATED_WILD_MON
call PlayBattleVictoryMusic
.sfxplayed
2016-06-12 04:30:05 +00:00
; bug: win sfx is played for wild battles before checking for player mon HP
; this can lead to odd scenarios where both player and enemy faint, as the win sfx plays yet the player never won the battle
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
or [hl]
jr nz, .playermonnotfaint
2015-08-14 07:36:06 +00:00
ld a, [wInHandlePlayerMonFainted]
and a ; was this called by HandlePlayerMonFainted?
jr nz, .playermonnotfaint ; if so, don't call RemoveFaintedPlayerMon twice
2014-08-09 05:39:13 +00:00
call RemoveFaintedPlayerMon
2014-05-22 22:13:20 +00:00
.playermonnotfaint
call AnyPartyAlive
2014-05-22 22:13:20 +00:00
ld a, d
and a
ret z
ld hl, EnemyMonFaintedText
call PrintText
2014-08-09 05:39:13 +00:00
call PrintEmptyString
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
xor a
2014-08-09 05:39:13 +00:00
ld [wBattleResult], a
2015-12-15 04:09:30 +00:00
ld b, EXP_ALL
2014-05-22 22:13:20 +00:00
call IsItemInBag
push af
2014-08-09 05:39:13 +00:00
jr z, .giveExpToMonsThatFought ; if no exp all, then jump
; the player has exp all
; first, we halve the values that determine exp gain
; the enemy mon base stats are added to stat exp, so they are halved
; the base exp (which determines normal exp) is also halved
ld hl, wEnemyMonBaseStats
2014-05-22 22:13:20 +00:00
ld b, $7
2014-08-09 05:39:13 +00:00
.halveExpDataLoop
2014-05-22 22:13:20 +00:00
srl [hl]
inc hl
dec b
2014-08-09 05:39:13 +00:00
jr nz, .halveExpDataLoop
; give exp (divided evenly) to the mons that actually fought in battle against the enemy mon that has fainted
; if exp all is in the bag, this will be only be half of the stat exp and normal exp, due to the above loop
.giveExpToMonsThatFought
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 18:28:42 +00:00
ld [wBoostExpByExpAll], a
2014-05-22 22:13:20 +00:00
callab GainExperience
pop af
2014-08-09 05:39:13 +00:00
ret z ; return if no exp all
; the player has exp all
; now, set the gain exp flag for every party member
; half of the total stat exp and normal exp will divided evenly amongst every party member
2014-05-22 22:13:20 +00:00
ld a, $1
2015-03-31 18:28:42 +00:00
ld [wBoostExpByExpAll], a
2014-08-09 05:39:13 +00:00
ld a, [wPartyCount]
ld b, 0
.gainExpFlagsLoop
2014-05-22 22:13:20 +00:00
scf
rl b
dec a
2014-08-09 05:39:13 +00:00
jr nz, .gainExpFlagsLoop
2014-05-22 22:13:20 +00:00
ld a, b
2014-08-09 05:39:13 +00:00
ld [wPartyGainExpFlags], a
2015-07-19 18:56:13 +00:00
jpab GainExperience
2014-05-22 22:13:20 +00:00
EnemyMonFaintedText:
2014-05-22 22:13:20 +00:00
TX_FAR _EnemyMonFaintedText
db "@"
2016-06-12 00:24:04 +00:00
EndLowHealthAlarm:
2015-08-14 07:36:06 +00:00
; This function is called when the player has the won the battle. It turns off
; the low health alarm and prevents it from reactivating until the next battle.
2014-05-22 22:13:20 +00:00
xor a
2015-08-14 07:36:06 +00:00
ld [wLowHealthAlarm], a ; turn off low health alarm
ld [wChannelSoundIDs + Ch5], a
2014-05-22 22:13:20 +00:00
inc a
2015-08-14 07:36:06 +00:00
ld [wLowHealthAlarmDisabled], a ; prevent it from reactivating
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
AnyEnemyPokemonAliveCheck:
2014-08-09 05:39:13 +00:00
ld a, [wEnemyPartyCount]
2014-05-22 22:13:20 +00:00
ld b, a
xor a
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMon1HP
ld de, wEnemyMon2 - wEnemyMon1
.nextPokemon
2014-05-22 22:13:20 +00:00
or [hl]
inc hl
or [hl]
dec hl
add hl, de
dec b
jr nz, .nextPokemon
2014-05-22 22:13:20 +00:00
and a
ret
2014-08-09 05:39:13 +00:00
; stores whether enemy ran in Z flag
2016-06-12 00:24:04 +00:00
ReplaceFaintedEnemyMon:
2015-08-12 09:16:56 +00:00
ld hl, wEnemyHPBarColor
2014-05-22 22:13:20 +00:00
ld e, $30
call GetBattleHealthBarColor
callab DrawEnemyPokeballs
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
jr nz, .notLinkBattle
2014-08-09 05:39:13 +00:00
; link battle
call LinkBattleExchangeData
2015-02-07 10:43:08 +00:00
ld a, [wSerialExchangeNybbleReceiveData]
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_RUN
2014-05-22 22:13:20 +00:00
ret z
call LoadScreenTilesFromBuffer1
.notLinkBattle
2014-05-22 22:13:20 +00:00
call EnemySendOut
xor a
2015-08-31 02:38:41 +00:00
ld [wEnemyMoveNum], a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2015-03-31 18:40:22 +00:00
ld [wAILayer2Encouragement], a
2014-08-09 05:39:13 +00:00
inc a ; reset Z flag
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
TrainerBattleVictory:
2015-03-31 18:50:49 +00:00
call EndLowHealthAlarm
2014-05-22 22:13:20 +00:00
ld b, MUSIC_DEFEATED_GYM_LEADER
2015-08-31 02:38:41 +00:00
ld a, [wGymLeaderNo]
2014-05-22 22:13:20 +00:00
and a
jr nz, .gymleader
ld b, MUSIC_DEFEATED_TRAINER
.gymleader
2015-08-31 02:38:41 +00:00
ld a, [wTrainerClass]
2014-05-22 22:13:20 +00:00
cp SONY3 ; final battle against rival
jr nz, .notrival
ld b, MUSIC_DEFEATED_GYM_LEADER
2015-08-31 02:38:41 +00:00
ld hl, wFlags_D733
2014-05-22 22:13:20 +00:00
set 1, [hl]
.notrival
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
ld a, b
call nz, PlayBattleVictoryMusic
ld hl, TrainerDefeatedText
call PrintText
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
ret z
call ScrollTrainerPicAfterBattle
ld c, 40
2014-05-22 22:13:20 +00:00
call DelayFrames
2014-09-14 18:29:18 +00:00
call PrintEndBattleText
2015-06-11 22:41:33 +00:00
; win money
2014-05-22 22:13:20 +00:00
ld hl, MoneyForWinningText
call PrintText
2014-08-09 05:39:13 +00:00
ld de, wPlayerMoney + 2
2015-04-09 11:05:57 +00:00
ld hl, wAmountMoneyWon + 2
2014-05-22 22:13:20 +00:00
ld c, $3
predef_jump AddBCDPredef
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
MoneyForWinningText:
2014-05-22 22:13:20 +00:00
TX_FAR _MoneyForWinningText
db "@"
2016-06-12 00:24:04 +00:00
TrainerDefeatedText:
2014-05-22 22:13:20 +00:00
TX_FAR _TrainerDefeatedText
db "@"
2016-06-12 00:24:04 +00:00
PlayBattleVictoryMusic:
2014-05-22 22:13:20 +00:00
push af
ld a, $ff
2015-08-09 05:32:44 +00:00
ld [wNewSoundID], a
2014-05-22 22:13:20 +00:00
call PlaySoundWaitForCurrent
ld c, BANK(Music_DefeatedTrainer)
pop af
call PlayMusic
jp Delay3
2016-06-12 00:24:04 +00:00
HandlePlayerMonFainted:
2015-08-14 07:36:06 +00:00
ld a, 1
ld [wInHandlePlayerMonFainted], a
2014-08-09 05:39:13 +00:00
call RemoveFaintedPlayerMon
call AnyPartyAlive ; test if any more mons are alive
2014-05-22 22:13:20 +00:00
ld a, d
and a
jp z, HandlePlayerBlackOut
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
or [hl] ; is enemy mon's HP 0?
jr nz, .doUseNextMonDialogue ; if not, jump
; the enemy mon has 0 HP
2014-05-22 22:13:20 +00:00
call FaintEnemyPokemon
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
ret z ; if wild encounter, battle is over
call AnyEnemyPokemonAliveCheck
jp z, TrainerBattleVictory
2014-08-09 05:39:13 +00:00
.doUseNextMonDialogue
call DoUseNextMonDialogue
ret c ; return if the player ran from battle
call ChooseNextMon
jp nz, MainInBattleLoop ; if the enemy mon has more than 0 HP, go back to battle loop
; the enemy mon has 0 HP
2014-05-22 22:13:20 +00:00
ld a, $1
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-08-09 05:39:13 +00:00
call ReplaceFaintedEnemyMon
jp z, EnemyRan ; if enemy ran from battle rather than sending out another mon, jump
2014-05-22 22:13:20 +00:00
xor a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-05-22 22:13:20 +00:00
jp MainInBattleLoop
2014-08-09 05:39:13 +00:00
; resets flags, slides mon's pic down, plays cry, and prints fainted message
2016-06-12 00:24:04 +00:00
RemoveFaintedPlayerMon:
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMonNumber]
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
ld hl, wPartyGainExpFlags
2015-07-20 03:45:34 +00:00
ld b, FLAG_RESET
2014-08-09 05:39:13 +00:00
predef FlagActionPredef ; clear gain exp flag for fainted mon
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-05-22 22:13:20 +00:00
res 2, [hl] ; reset "attacking multiple times" flag
ld a, [wLowHealthAlarm]
2014-05-22 22:13:20 +00:00
bit 7, a ; skip sound flag (red bar (?))
jr z, .skipWaitForSound
ld a, $ff
ld [wLowHealthAlarm], a ;disable low health alarm
2014-05-22 22:13:20 +00:00
call WaitForSoundToFinish
.skipWaitForSound
2015-08-07 06:53:23 +00:00
; a is 0, so this zeroes the enemy's accumulated damage.
2015-02-07 12:23:34 +00:00
ld hl, wEnemyBideAccumulatedDamage
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hl], a
2014-08-09 05:39:13 +00:00
ld [wBattleMonStatus], a
2014-05-22 22:13:20 +00:00
call ReadPlayerMonCurHPAndStatus
2015-07-18 20:52:03 +00:00
coord hl, 9, 7
2015-08-05 21:20:29 +00:00
lb bc, 5, 11
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2015-07-18 20:52:03 +00:00
coord hl, 1, 10
coord de, 1, 11
2014-08-09 05:39:13 +00:00
call SlideDownFaintedMonPic
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [wBattleResult], a
2015-08-14 07:36:06 +00:00
; When the player mon and enemy mon faint at the same time and the fact that the
; enemy mon has fainted is detected first (e.g. when the player mon knocks out
; the enemy mon using a move with recoil and faints due to the recoil), don't
; play the player mon's cry or show the "[player mon] fainted!" message.
ld a, [wInHandlePlayerMonFainted]
and a ; was this called by HandleEnemyMonFainted?
ret z ; if so, return
ld a, [wBattleMonSpecies]
2014-05-22 22:13:20 +00:00
call PlayCry
ld hl, PlayerMonFaintedText
jp PrintText
2016-06-12 00:24:04 +00:00
PlayerMonFaintedText:
2014-05-22 22:13:20 +00:00
TX_FAR _PlayerMonFaintedText
db "@"
2014-08-09 05:39:13 +00:00
; asks if you want to use next mon
; stores whether you ran in C flag
2016-06-12 00:24:04 +00:00
DoUseNextMonDialogue:
2014-08-09 05:39:13 +00:00
call PrintEmptyString
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
and a
dec a
2014-08-09 05:39:13 +00:00
ret nz ; return if it's a trainer battle
2014-05-22 22:13:20 +00:00
ld hl, UseNextMonText
call PrintText
2014-08-09 05:39:13 +00:00
.displayYesNoBox
2015-07-18 20:52:03 +00:00
coord hl, 13, 9
2015-08-05 21:20:29 +00:00
lb bc, 10, 14
2015-02-07 20:27:36 +00:00
ld a, TWO_OPTION_MENU
2015-02-07 10:43:08 +00:00
ld [wTextBoxID], a
2014-05-22 22:13:20 +00:00
call DisplayTextBoxID
2015-07-13 06:00:48 +00:00
ld a, [wMenuExitMethod]
cp CHOSE_SECOND_ITEM ; did the player choose NO?
2014-08-09 05:39:13 +00:00
jr z, .tryRunning ; if the player chose NO, try running
and a ; reset carry
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
.tryRunning
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .displayYesNoBox ; xxx when does this happen?
ld hl, wPartyMon1Speed
ld de, wEnemyMonSpeed
2014-08-09 05:39:13 +00:00
jp TryRunningFromBattle
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
UseNextMonText:
2014-05-22 22:13:20 +00:00
TX_FAR _UseNextMonText
db "@"
2014-08-09 05:39:13 +00:00
; choose next player mon to send out
; stores whether enemy mon has no HP left in Z flag
2016-06-12 00:24:04 +00:00
ChooseNextMon:
ld a, BATTLE_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
2014-05-22 22:13:20 +00:00
call DisplayPartyMenu
2014-08-09 05:39:13 +00:00
.checkIfMonChosen
jr nc, .monChosen
.goBackToPartyMenu
2014-05-22 22:13:20 +00:00
call GoBackToPartyMenu
2014-08-09 05:39:13 +00:00
jr .checkIfMonChosen
.monChosen
call HasMonFainted
jr z, .goBackToPartyMenu ; if mon fainted, you have to choose another
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
jr nz, .notLinkBattle
2014-05-22 22:13:20 +00:00
inc a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-08-09 05:39:13 +00:00
call LinkBattleExchangeData
.notLinkBattle
2014-05-22 22:13:20 +00:00
xor a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-05-23 22:34:35 +00:00
call ClearSprites
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld [wPlayerMonNumber], a
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
ld hl, wPartyGainExpFlags
2015-07-20 03:45:34 +00:00
ld b, FLAG_SET
2014-05-22 22:13:20 +00:00
push bc
predef FlagActionPredef
2014-05-22 22:13:20 +00:00
pop bc
2014-08-09 05:39:13 +00:00
ld hl, wPartyFoughtCurrentEnemyFlags
predef FlagActionPredef
2014-08-09 05:39:13 +00:00
call LoadBattleMonFromParty
2014-05-22 22:13:20 +00:00
call GBPalWhiteOut
2014-08-09 05:39:13 +00:00
call LoadHudTilePatterns
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-08-12 09:16:56 +00:00
call RunDefaultPaletteCommand
2014-05-22 22:13:20 +00:00
call GBPalNormal
2014-08-09 05:39:13 +00:00
call SendOutMon
ld hl, wEnemyMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
or [hl]
ret
; called when player is out of usable mons.
2017-06-24 20:01:43 +00:00
; prints appropriate lose message, sets carry flag if player blacked out (special case for initial rival fight)
2016-06-12 00:24:04 +00:00
HandlePlayerBlackOut:
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
jr z, .notSony1Battle
2015-08-31 02:38:41 +00:00
ld a, [wCurOpponent]
cp OPP_SONY1
2014-05-22 22:13:20 +00:00
jr nz, .notSony1Battle
2015-07-18 20:52:03 +00:00
coord hl, 0, 0 ; sony 1 battle
2015-08-05 21:20:29 +00:00
lb bc, 8, 21
2014-05-22 22:13:20 +00:00
call ClearScreenArea
call ScrollTrainerPicAfterBattle
ld c, 40
2014-05-22 22:13:20 +00:00
call DelayFrames
ld hl, Sony1WinText
call PrintText
2015-08-31 02:38:41 +00:00
ld a, [wCurMap]
2014-05-22 22:13:20 +00:00
cp OAKS_LAB
ret z ; starter battle in oak's lab: don't black out
.notSony1Battle
2015-08-12 09:16:56 +00:00
ld b, SET_PAL_BATTLE_BLACK
call RunPaletteCommand
2014-05-22 22:13:20 +00:00
ld hl, PlayerBlackedOutText2
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
jr nz, .noLinkBattle
ld hl, LinkBattleLostText
.noLinkBattle
call PrintText
ld a, [wd732]
2014-05-22 22:13:20 +00:00
res 5, a
ld [wd732], a
2014-05-22 22:13:20 +00:00
call ClearScreen
scf
ret
2016-06-12 00:24:04 +00:00
Sony1WinText:
2014-05-22 22:13:20 +00:00
TX_FAR _Sony1WinText
db "@"
2016-06-12 00:24:04 +00:00
PlayerBlackedOutText2:
2014-05-22 22:13:20 +00:00
TX_FAR _PlayerBlackedOutText2
db "@"
2016-06-12 00:24:04 +00:00
LinkBattleLostText:
2014-05-22 22:13:20 +00:00
TX_FAR _LinkBattleLostText
db "@"
2014-08-09 05:39:13 +00:00
; slides pic of fainted mon downwards until it disappears
; bug: when this is called, [H_AUTOBGTRANSFERENABLED] is non-zero, so there is screen tearing
2016-06-12 00:24:04 +00:00
SlideDownFaintedMonPic:
ld a, [wd730]
2014-05-22 22:13:20 +00:00
push af
set 6, a
ld [wd730], a
2014-08-09 05:39:13 +00:00
ld b, 7 ; number of times to slide
.slideStepLoop ; each iteration, the mon is slid down one row
2014-05-22 22:13:20 +00:00
push bc
push de
push hl
2014-08-09 05:39:13 +00:00
ld b, 6 ; number of rows
.rowLoop
2014-05-22 22:13:20 +00:00
push bc
push hl
push de
ld bc, $7
call CopyData
pop de
pop hl
2016-06-12 04:30:05 +00:00
ld bc, -SCREEN_WIDTH
2014-05-22 22:13:20 +00:00
add hl, bc
push hl
ld h, d
ld l, e
add hl, bc
ld d, h
ld e, l
pop hl
pop bc
dec b
2014-08-09 05:39:13 +00:00
jr nz, .rowLoop
2016-06-12 04:30:05 +00:00
ld bc, SCREEN_WIDTH
2014-05-22 22:13:20 +00:00
add hl, bc
ld de, SevenSpacesText
call PlaceString
2014-08-09 05:39:13 +00:00
ld c, 2
2014-05-22 22:13:20 +00:00
call DelayFrames
pop hl
pop de
pop bc
dec b
2014-08-09 05:39:13 +00:00
jr nz, .slideStepLoop
2014-05-22 22:13:20 +00:00
pop af
ld [wd730], a
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
SevenSpacesText:
2014-05-22 22:13:20 +00:00
db " @"
2014-08-09 05:39:13 +00:00
; slides the player or enemy trainer off screen
; a is the number of tiles to slide it horizontally (always 9 for the player trainer or 8 for the enemy trainer)
; if a is 8, the slide is to the right, else it is to the left
; bug: when this is called, [H_AUTOBGTRANSFERENABLED] is non-zero, so there is screen tearing
2016-06-12 00:24:04 +00:00
SlideTrainerPicOffScreen:
2015-07-18 15:17:29 +00:00
ld [hSlideAmount], a
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
.slideStepLoop ; each iteration, the trainer pic is slid one tile left/right
2014-05-22 22:13:20 +00:00
push bc
push hl
2014-08-09 05:39:13 +00:00
ld b, 7 ; number of rows
.rowLoop
2014-05-22 22:13:20 +00:00
push hl
2015-07-18 15:17:29 +00:00
ld a, [hSlideAmount]
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
.columnLoop
2015-07-18 15:17:29 +00:00
ld a, [hSlideAmount]
2014-08-09 05:39:13 +00:00
cp 8
jr z, .slideRight
.slideLeft ; slide player sprite off screen
2014-05-22 22:13:20 +00:00
ld a, [hld]
ld [hli], a
inc hl
2014-08-09 05:39:13 +00:00
jr .nextColumn
.slideRight ; slide enemy trainer sprite off screen
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [hld], a
dec hl
2014-08-09 05:39:13 +00:00
.nextColumn
2014-05-22 22:13:20 +00:00
dec c
2014-08-09 05:39:13 +00:00
jr nz, .columnLoop
2014-05-22 22:13:20 +00:00
pop hl
2014-08-09 05:39:13 +00:00
ld de, 20
2014-05-22 22:13:20 +00:00
add hl, de
dec b
2014-08-09 05:39:13 +00:00
jr nz, .rowLoop
ld c, 2
2014-05-22 22:13:20 +00:00
call DelayFrames
pop hl
pop bc
dec c
2014-08-09 05:39:13 +00:00
jr nz, .slideStepLoop
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; send out a trainer's mon
2016-06-12 00:24:04 +00:00
EnemySendOut:
ld hl, wPartyGainExpFlags
2014-05-22 22:13:20 +00:00
xor a
ld [hl], a
ld a, [wPlayerMonNumber]
ld c, a
ld b, FLAG_SET
2014-05-22 22:13:20 +00:00
push bc
predef FlagActionPredef
ld hl, wPartyFoughtCurrentEnemyFlags
2014-05-22 22:13:20 +00:00
xor a
ld [hl], a
2014-05-22 22:13:20 +00:00
pop bc
predef FlagActionPredef
2014-08-09 05:39:13 +00:00
; don't change wPartyGainExpFlags or wPartyFoughtCurrentEnemyFlags
2016-06-12 00:24:04 +00:00
EnemySendOutFirstMon:
2014-05-22 22:13:20 +00:00
xor a
ld hl, wEnemyStatsToDouble ; clear enemy statuses
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld [wEnemyDisabledMove], a
ld [wEnemyDisabledMoveNumber], a
ld [wEnemyMonMinimized], a
ld hl, wPlayerUsedMove
ld [hli], a
ld [hl], a
2014-05-22 22:13:20 +00:00
dec a
ld [wAICount], a
ld hl, wPlayerBattleStatus1
res 5, [hl]
2015-07-18 20:52:03 +00:00
coord hl, 18, 0
ld a, 8
2014-08-09 05:39:13 +00:00
call SlideTrainerPicOffScreen
call PrintEmptyString
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
ld a, [wLinkState]
2015-02-07 10:43:08 +00:00
cp LINK_STATE_BATTLING
jr nz, .next
ld a, [wSerialExchangeNybbleReceiveData]
2014-05-22 22:13:20 +00:00
sub 4
ld [wWhichPokemon], a
2014-05-22 22:13:20 +00:00
jr .next3
.next
ld b, $FF
2014-05-22 22:13:20 +00:00
.next2
inc b
ld a, [wEnemyMonPartyPos]
2014-05-22 22:13:20 +00:00
cp b
jr z, .next2
ld hl, wEnemyMon1
ld a, b
ld [wWhichPokemon], a
2014-05-22 22:13:20 +00:00
push bc
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
pop bc
inc hl
ld a, [hli]
ld c, a
ld a, [hl]
2014-05-22 22:13:20 +00:00
or c
jr z, .next2
2014-05-22 22:13:20 +00:00
.next3
ld a, [wWhichPokemon]
ld hl, wEnemyMon1Level
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, [hl]
ld [wCurEnemyLVL], a
ld a, [wWhichPokemon]
2014-05-22 22:13:20 +00:00
inc a
ld hl, wEnemyPartyCount
ld c, a
ld b, 0
add hl, bc
ld a, [hl]
ld [wEnemyMonSpecies2], a
ld [wcf91], a
2014-08-09 05:39:13 +00:00
call LoadEnemyMonData
ld hl, wEnemyMonHP
ld a, [hli]
ld [wLastSwitchInEnemyMonHP], a
ld a, [hl]
ld [wLastSwitchInEnemyMonHP + 1], a
ld a, 1
ld [wCurrentMenuItem], a
ld a, [wFirstMonsNotOutYet]
2014-05-22 22:13:20 +00:00
dec a
jr z, .next4
ld a, [wPartyCount]
2014-05-22 22:13:20 +00:00
dec a
jr z, .next4
ld a, [wLinkState]
2015-02-07 10:43:08 +00:00
cp LINK_STATE_BATTLING
jr z, .next4
ld a, [wOptions]
bit 6, a
jr nz, .next4
2014-05-22 22:13:20 +00:00
ld hl, TrainerAboutToUseText
call PrintText
2015-07-18 20:52:03 +00:00
coord hl, 0, 7
2015-08-05 21:20:29 +00:00
lb bc, 8, 1
ld a, TWO_OPTION_MENU
ld [wTextBoxID], a
2014-05-22 22:13:20 +00:00
call DisplayTextBoxID
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
and a
jr nz, .next4
ld a, BATTLE_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
2014-05-22 22:13:20 +00:00
call DisplayPartyMenu
.next9
ld a, 1
ld [wCurrentMenuItem], a
jr c, .next7
ld hl, wPlayerMonNumber
ld a, [wWhichPokemon]
2014-05-22 22:13:20 +00:00
cp [hl]
jr nz, .next6
ld hl, AlreadyOutText
2014-05-22 22:13:20 +00:00
call PrintText
.next8
call GoBackToPartyMenu
jr .next9
.next6
2014-08-09 05:39:13 +00:00
call HasMonFainted
jr z, .next8
2014-05-22 22:13:20 +00:00
xor a
ld [wCurrentMenuItem], a
2014-05-22 22:13:20 +00:00
.next7
call GBPalWhiteOut
2014-08-09 05:39:13 +00:00
call LoadHudTilePatterns
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
.next4
2014-05-23 22:34:35 +00:00
call ClearSprites
2015-07-18 20:52:03 +00:00
coord hl, 0, 0
2015-08-05 21:20:29 +00:00
lb bc, 4, 11
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2015-08-12 09:16:56 +00:00
ld b, SET_PAL_BATTLE
call RunPaletteCommand
2014-05-22 22:13:20 +00:00
call GBPalNormal
ld hl, TrainerSentOutText
2014-05-22 22:13:20 +00:00
call PrintText
ld a, [wEnemyMonSpecies2]
ld [wcf91], a
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
ld de, vFrontPic
2014-05-22 22:13:20 +00:00
call LoadMonFrontSprite
ld a, -$31
ld [hStartTileID], a
2015-07-18 20:52:03 +00:00
coord hl, 15, 6
predef AnimateSendingOutMon
ld a, [wEnemyMonSpecies2]
2014-05-22 22:13:20 +00:00
call PlayCry
2014-08-09 05:39:13 +00:00
call DrawEnemyHUDAndHPBar
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
and a
ret nz
xor a
ld [wPartyGainExpFlags], a
ld [wPartyFoughtCurrentEnemyFlags], a
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
2014-08-09 05:39:13 +00:00
jp SwitchPlayerMon
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
TrainerAboutToUseText:
2014-05-22 22:13:20 +00:00
TX_FAR _TrainerAboutToUseText
db "@"
2016-06-12 00:24:04 +00:00
TrainerSentOutText:
2014-05-22 22:13:20 +00:00
TX_FAR _TrainerSentOutText
db "@"
; tests if the player has any pokemon that are not fainted
; sets d = 0 if all fainted, d != 0 if some mons are still alive
2016-06-12 00:24:04 +00:00
AnyPartyAlive:
2014-08-09 05:39:13 +00:00
ld a, [wPartyCount]
2014-05-22 22:13:20 +00:00
ld e, a
xor a
2014-08-09 05:39:13 +00:00
ld hl, wPartyMon1HP
ld bc, wPartyMon2 - wPartyMon1 - 1
2014-05-22 22:13:20 +00:00
.partyMonsLoop
or [hl]
inc hl
or [hl]
add hl, bc
dec e
jr nz, .partyMonsLoop
ld d, a
ret
2014-08-09 05:39:13 +00:00
; tests if player mon has fainted
; stores whether mon has fainted in Z flag
2016-06-12 00:24:04 +00:00
HasMonFainted:
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld hl, wPartyMon1HP
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, [hli]
or [hl]
ret nz
2015-07-25 03:27:59 +00:00
ld a, [wFirstMonsNotOutYet]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr nz, .done
2014-05-22 22:13:20 +00:00
ld hl, NoWillText
call PrintText
2014-08-09 05:39:13 +00:00
.done
2014-05-22 22:13:20 +00:00
xor a
ret
2016-06-12 00:24:04 +00:00
NoWillText:
2014-05-22 22:13:20 +00:00
TX_FAR _NoWillText
db "@"
2014-08-09 05:39:13 +00:00
; try to run from battle (hl = player speed, de = enemy speed)
; stores whether the attempt was successful in carry flag
2016-06-12 00:24:04 +00:00
TryRunningFromBattle:
2014-05-22 22:13:20 +00:00
call IsGhostBattle
2014-08-09 05:39:13 +00:00
jp z, .canEscape ; jump if it's a ghost battle
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-08-09 05:39:13 +00:00
jp z, .canEscape ; jump if it's a safari battle
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-08-09 05:39:13 +00:00
jp z, .canEscape
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
jr nz, .trainerBattle ; jump if it's a trainer battle
ld a, [wNumRunAttempts]
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld [wNumRunAttempts], a
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-07-18 15:17:29 +00:00
ld [hEnemySpeed], a
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
2015-07-18 15:17:29 +00:00
ld [hEnemySpeed + 1], a
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2014-08-09 05:39:13 +00:00
ld de, H_MULTIPLICAND + 1
2015-07-18 15:17:29 +00:00
ld hl, hEnemySpeed
ld c, 2
2014-05-22 22:13:20 +00:00
call StringCmp
2014-08-09 05:39:13 +00:00
jr nc, .canEscape ; jump if player speed greater than enemy speed
xor a
2015-01-23 03:05:13 +00:00
ld [H_MULTIPLICAND], a
2014-08-09 05:39:13 +00:00
ld a, 32
ld [H_MULTIPLIER], a
call Multiply ; multiply player speed by 32
ld a, [H_PRODUCT + 2]
ld [H_DIVIDEND], a
ld a, [H_PRODUCT + 3]
ld [H_DIVIDEND + 1], a
2015-07-18 15:17:29 +00:00
ld a, [hEnemySpeed]
2014-05-22 22:13:20 +00:00
ld b, a
2015-07-18 15:17:29 +00:00
ld a, [hEnemySpeed + 1]
2014-08-09 05:39:13 +00:00
; divide enemy speed by 4
2014-05-22 22:13:20 +00:00
srl b
rr a
srl b
rr a
and a
2014-08-09 05:39:13 +00:00
jr z, .canEscape ; jump if enemy speed divided by 4, mod 256 is 0
ld [H_DIVISOR], a ; ((enemy speed / 4) % 256)
2014-05-22 22:13:20 +00:00
ld b, $2
2014-08-09 05:39:13 +00:00
call Divide ; divide (player speed * 32) by ((enemy speed / 4) % 256)
ld a, [H_QUOTIENT + 2]
and a ; is the quotient greater than 256?
jr nz, .canEscape ; if so, the player can escape
ld a, [wNumRunAttempts]
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
; add 30 to the quotient for each run attempt
.loop
2014-05-22 22:13:20 +00:00
dec c
2014-08-09 05:39:13 +00:00
jr z, .compareWithRandomValue
ld b, 30
ld a, [H_QUOTIENT + 3]
2014-05-22 22:13:20 +00:00
add b
2014-08-09 05:39:13 +00:00
ld [H_QUOTIENT + 3], a
jr c, .canEscape
jr .loop
.compareWithRandomValue
call BattleRandom
2014-05-22 22:13:20 +00:00
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [H_QUOTIENT + 3]
2014-05-22 22:13:20 +00:00
cp b
2015-06-11 22:41:33 +00:00
jr nc, .canEscape ; if the random value was less than or equal to the quotient
; plus 30 times the number of attempts, the player can escape
2014-08-09 05:39:13 +00:00
; can't escape
2014-05-22 22:13:20 +00:00
ld a, $1
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a ; you lose your turn when you can't escape
2014-05-22 22:13:20 +00:00
ld hl, CantEscapeText
2014-08-09 05:39:13 +00:00
jr .printCantEscapeOrNoRunningText
.trainerBattle
2014-05-22 22:13:20 +00:00
ld hl, NoRunningText
2014-08-09 05:39:13 +00:00
.printCantEscapeOrNoRunningText
2014-05-22 22:13:20 +00:00
call PrintText
2015-07-25 03:27:59 +00:00
ld a, 1
ld [wForcePlayerToChooseMon], a
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
2014-08-09 05:39:13 +00:00
and a ; reset carry
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
.canEscape
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
ld a, $2
2014-08-09 05:39:13 +00:00
jr nz, .playSound
; link battle
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
xor a
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2016-10-29 08:44:13 +00:00
ld a, LINKBATTLE_RUN
2014-08-09 05:39:13 +00:00
ld [wPlayerMoveListIndex], a
call LinkBattleExchangeData
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-02-07 10:43:08 +00:00
ld a, [wSerialExchangeNybbleReceiveData]
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_RUN
2014-05-22 22:13:20 +00:00
ld a, $2
2014-08-09 05:39:13 +00:00
jr z, .playSound
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
.playSound
ld [wBattleResult], a
2015-07-22 01:58:19 +00:00
ld a, SFX_RUN
2014-05-22 22:13:20 +00:00
call PlaySoundWaitForCurrent
ld hl, GotAwayText
call PrintText
call WaitForSoundToFinish
call SaveScreenTilesToBuffer1
2014-08-09 05:39:13 +00:00
scf ; set carry
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
CantEscapeText:
2014-05-22 22:13:20 +00:00
TX_FAR _CantEscapeText
db "@"
2016-06-12 00:24:04 +00:00
NoRunningText:
2014-05-22 22:13:20 +00:00
TX_FAR _NoRunningText
db "@"
2016-06-12 00:24:04 +00:00
GotAwayText:
2014-05-22 22:13:20 +00:00
TX_FAR _GotAwayText
db "@"
2014-08-09 05:39:13 +00:00
; copies from party data to battle mon data when sending out a new player mon
2016-06-12 00:24:04 +00:00
LoadBattleMonFromParty:
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld bc, wPartyMon2 - wPartyMon1
2014-08-09 05:39:13 +00:00
ld hl, wPartyMon1Species
2014-05-22 22:13:20 +00:00
call AddNTimes
ld de, wBattleMonSpecies
ld bc, wBattleMonDVs - wBattleMonSpecies
2014-05-22 22:13:20 +00:00
call CopyData
ld bc, wPartyMon1DVs - wPartyMon1OTID
2014-05-22 22:13:20 +00:00
add hl, bc
ld de, wBattleMonDVs
ld bc, NUM_DVS
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld de, wBattleMonPP
ld bc, NUM_MOVES
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld de, wBattleMonLevel
ld bc, wBattleMonPP - wBattleMonLevel
2014-05-22 22:13:20 +00:00
call CopyData
ld a, [wBattleMonSpecies2]
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
2014-08-09 05:39:13 +00:00
ld hl, wPartyMonNicks
ld a, [wPlayerMonNumber]
2014-05-22 22:13:20 +00:00
call SkipFixedLengthTextEntries
ld de, wBattleMonNick
ld bc, NAME_LENGTH
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonLevel
ld de, wPlayerMonUnmodifiedLevel ; block of memory used for unmodified stats
ld bc, 1 + NUM_STATS * 2
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
call ApplyBurnAndParalysisPenaltiesToPlayer
call ApplyBadgeStatBoosts
ld a, $7 ; default stat modifier
ld b, NUM_STAT_MODS
2014-08-09 05:39:13 +00:00
ld hl, wPlayerMonAttackMod
.statModLoop
2014-05-22 22:13:20 +00:00
ld [hli], a
dec b
2014-08-09 05:39:13 +00:00
jr nz, .statModLoop
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; copies from enemy party data to current enemy mon data when sending out a new enemy mon
2016-06-12 00:24:04 +00:00
LoadEnemyMonFromParty:
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld bc, wEnemyMon2 - wEnemyMon1
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMons
2014-05-22 22:13:20 +00:00
call AddNTimes
ld de, wEnemyMonSpecies
ld bc, wEnemyMonDVs - wEnemyMonSpecies
2014-05-22 22:13:20 +00:00
call CopyData
ld bc, wEnemyMon1DVs - wEnemyMon1OTID
2014-05-22 22:13:20 +00:00
add hl, bc
ld de, wEnemyMonDVs
ld bc, NUM_DVS
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonPP
ld bc, NUM_MOVES
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonLevel
ld bc, wEnemyMonPP - wEnemyMonLevel
2014-05-22 22:13:20 +00:00
call CopyData
ld a, [wEnemyMonSpecies]
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
ld hl, wEnemyMonNicks
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
2014-05-22 22:13:20 +00:00
call SkipFixedLengthTextEntries
ld de, wEnemyMonNick
ld bc, NAME_LENGTH
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonLevel
ld de, wEnemyMonUnmodifiedLevel ; block of memory used for unmodified stats
ld bc, 1 + NUM_STATS * 2
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
call ApplyBurnAndParalysisPenaltiesToEnemy
2015-08-31 02:38:41 +00:00
ld hl, wMonHBaseStats
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonBaseStats
ld b, NUM_STATS
2014-08-09 05:39:13 +00:00
.copyBaseStatsLoop
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [de], a
inc de
dec b
2014-08-09 05:39:13 +00:00
jr nz, .copyBaseStatsLoop
ld a, $7 ; default stat modifier
ld b, NUM_STAT_MODS
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonStatMods
.statModLoop
2014-05-22 22:13:20 +00:00
ld [hli], a
dec b
2014-08-09 05:39:13 +00:00
jr nz, .statModLoop
ld a, [wWhichPokemon]
ld [wEnemyMonPartyPos], a
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
SendOutMon:
2014-08-09 05:39:13 +00:00
callab PrintSendOutMonMessage
ld hl, wEnemyMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
or [hl] ; is enemy mon HP zero?
jp z, .skipDrawingEnemyHUDAndHPBar; if HP is zero, skip drawing the HUD and HP bar
call DrawEnemyHUDAndHPBar
.skipDrawingEnemyHUDAndHPBar
call DrawPlayerHUDAndHPBar
predef LoadMonBackPic
2014-05-22 22:13:20 +00:00
xor a
2015-07-24 03:48:35 +00:00
ld [hStartTileID], a
2015-07-16 03:04:58 +00:00
ld hl, wBattleAndStartSavedMenuItem
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hl], a
2015-03-31 18:28:42 +00:00
ld [wBoostExpByExpAll], a
ld [wDamageMultipliers], a
2015-08-31 02:38:41 +00:00
ld [wPlayerMoveNum], a
ld hl, wPlayerUsedMove
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hl], a
2015-02-08 09:44:41 +00:00
ld hl, wPlayerStatsToDouble
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
2015-08-31 02:38:41 +00:00
ld [wPlayerDisabledMove], a
ld [wPlayerDisabledMoveNumber], a
2015-07-12 22:51:04 +00:00
ld [wPlayerMonMinimized], a
2015-08-12 09:16:56 +00:00
ld b, SET_PAL_BATTLE
call RunPaletteCommand
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res USING_TRAPPING_MOVE, [hl]
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
ld a, POOF_ANIM
call PlayMoveAnimation
2015-07-18 20:52:03 +00:00
coord hl, 4, 11
predef AnimateSendingOutMon
ld a, [wcf91]
2014-05-22 22:13:20 +00:00
call PlayCry
2014-08-09 05:39:13 +00:00
call PrintEmptyString
2014-05-22 22:13:20 +00:00
jp SaveScreenTilesToBuffer1
2015-07-15 06:16:06 +00:00
; show 2 stages of the player mon getting smaller before disappearing
2016-06-12 00:24:04 +00:00
AnimateRetreatingPlayerMon:
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
2015-07-24 03:48:35 +00:00
lb bc, 7, 7
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2015-07-18 20:52:03 +00:00
coord hl, 3, 7
2015-07-24 03:48:35 +00:00
lb bc, 5, 5
2014-05-22 22:13:20 +00:00
xor a
2015-07-15 06:16:06 +00:00
ld [wDownscaledMonSize], a
2015-07-24 03:48:35 +00:00
ld [hBaseTileID], a
2015-07-15 06:16:06 +00:00
predef CopyDownscaledMonTiles
ld c, 4
2014-05-22 22:13:20 +00:00
call DelayFrames
2014-08-09 05:39:13 +00:00
call .clearScreenArea
2015-07-18 20:52:03 +00:00
coord hl, 4, 9
2015-07-24 03:48:35 +00:00
lb bc, 3, 3
ld a, 1
2015-07-15 06:16:06 +00:00
ld [wDownscaledMonSize], a
2014-05-22 22:13:20 +00:00
xor a
2015-07-24 03:48:35 +00:00
ld [hBaseTileID], a
2015-07-15 06:16:06 +00:00
predef CopyDownscaledMonTiles
2014-05-22 22:13:20 +00:00
call Delay3
2014-08-09 05:39:13 +00:00
call .clearScreenArea
2014-05-22 22:13:20 +00:00
ld a, $4c
Coorda 5, 11
2014-08-09 05:39:13 +00:00
.clearScreenArea
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
2015-07-24 03:48:35 +00:00
lb bc, 7, 7
2014-05-22 22:13:20 +00:00
jp ClearScreenArea
; reads player's current mon's HP into wBattleMonHP
2016-06-12 00:24:04 +00:00
ReadPlayerMonCurHPAndStatus:
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMonNumber]
ld hl, wPartyMon1HP
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld d, h
ld e, l
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld bc, $4 ; 2 bytes HP, 1 byte unknown (unused?), 1 byte status
jp CopyData
2016-06-12 00:24:04 +00:00
DrawHUDsAndHPBars:
2014-08-09 05:39:13 +00:00
call DrawPlayerHUDAndHPBar
jp DrawEnemyHUDAndHPBar
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
DrawPlayerHUDAndHPBar:
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2015-07-18 20:52:03 +00:00
coord hl, 9, 7
2015-08-05 21:20:29 +00:00
lb bc, 5, 11
2014-05-22 22:13:20 +00:00
call ClearScreenArea
callab PlacePlayerHUDTiles
2015-07-18 20:52:03 +00:00
coord hl, 18, 9
2014-05-22 22:13:20 +00:00
ld [hl], $73
ld de, wBattleMonNick
2015-07-18 20:52:03 +00:00
coord hl, 10, 7
2014-08-09 05:39:13 +00:00
call CenterMonName
2014-05-22 22:13:20 +00:00
call PlaceString
ld hl, wBattleMonSpecies
2015-02-08 02:37:40 +00:00
ld de, wLoadedMon
ld bc, wBattleMonDVs - wBattleMonSpecies
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonLevel
2015-02-08 02:37:40 +00:00
ld de, wLoadedMonLevel
ld bc, wBattleMonPP - wBattleMonLevel
2014-05-22 22:13:20 +00:00
call CopyData
2015-07-18 20:52:03 +00:00
coord hl, 14, 8
2014-05-22 22:13:20 +00:00
push hl
inc hl
2015-02-08 02:37:40 +00:00
ld de, wLoadedMonStatus
2014-05-22 22:13:20 +00:00
call PrintStatusConditionNotFainted
pop hl
2016-06-12 04:30:05 +00:00
jr nz, .doNotPrintLevel
2014-05-22 22:13:20 +00:00
call PrintLevel
2016-06-12 04:30:05 +00:00
.doNotPrintLevel
2015-02-08 02:37:40 +00:00
ld a, [wLoadedMonSpecies]
ld [wcf91], a
2015-07-18 20:52:03 +00:00
coord hl, 10, 9
2015-01-23 03:05:13 +00:00
predef DrawHP
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2015-08-12 09:16:56 +00:00
ld hl, wPlayerHPBarColor
2014-05-22 22:13:20 +00:00
call GetBattleHealthBarColor
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
or [hl]
2016-06-12 04:30:05 +00:00
jr z, .fainted
2015-08-14 07:36:06 +00:00
ld a, [wLowHealthAlarmDisabled]
and a ; has the alarm been disabled because the player has already won?
ret nz ; if so, return
2015-08-12 09:16:56 +00:00
ld a, [wPlayerHPBarColor]
cp HP_BAR_RED
2016-06-12 04:30:05 +00:00
jr z, .setLowHealthAlarm
.fainted
ld hl, wLowHealthAlarm
bit 7, [hl] ;low health alarm enabled?
2014-05-22 22:13:20 +00:00
ld [hl], $0
ret z
xor a
ld [wChannelSoundIDs + Ch5], a
2014-05-22 22:13:20 +00:00
ret
2016-06-12 04:30:05 +00:00
.setLowHealthAlarm
ld hl, wLowHealthAlarm
set 7, [hl] ;enable low health alarm
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
DrawEnemyHUDAndHPBar:
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2015-07-18 20:52:03 +00:00
coord hl, 0, 0
2015-08-05 21:20:29 +00:00
lb bc, 4, 12
2014-05-22 22:13:20 +00:00
call ClearScreenArea
callab PlaceEnemyHUDTiles
ld de, wEnemyMonNick
2015-07-18 20:52:03 +00:00
coord hl, 1, 0
2014-08-09 05:39:13 +00:00
call CenterMonName
2014-05-22 22:13:20 +00:00
call PlaceString
2015-07-18 20:52:03 +00:00
coord hl, 4, 1
2014-05-22 22:13:20 +00:00
push hl
inc hl
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonStatus
2014-05-22 22:13:20 +00:00
call PrintStatusConditionNotFainted
pop hl
2014-08-09 05:39:13 +00:00
jr nz, .skipPrintLevel ; if the mon has a status condition, skip printing the level
ld a, [wEnemyMonLevel]
2015-02-08 02:37:40 +00:00
ld [wLoadedMonLevel], a
2014-05-22 22:13:20 +00:00
call PrintLevel
2014-08-09 05:39:13 +00:00
.skipPrintLevel
ld hl, wEnemyMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
ld a, [hld]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 2], a
or [hl] ; is current HP zero?
jr nz, .hpNonzero
; current HP is 0
; set variables for DrawHPBar
2014-05-22 22:13:20 +00:00
ld c, a
ld e, a
ld d, $6
2014-08-09 05:39:13 +00:00
jp .drawHPBar
.hpNonzero
xor a
ld [H_MULTIPLICAND], a
ld a, 48
ld [H_MULTIPLIER], a
call Multiply ; multiply current HP by 48
ld hl, wEnemyMonMaxHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, a
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [H_DIVISOR], a
2014-05-22 22:13:20 +00:00
ld a, b
2014-08-09 05:39:13 +00:00
and a ; is max HP > 255?
jr z, .doDivide
; if max HP > 255, scale both (current HP * 48) and max HP by dividing by 4 so that max HP fits in one byte
; (it needs to be one byte so it can be used as the divisor for the Divide function)
ld a, [H_DIVISOR]
2014-05-22 22:13:20 +00:00
srl b
rr a
srl b
rr a
2014-08-09 05:39:13 +00:00
ld [H_DIVISOR], a
ld a, [H_PRODUCT + 2]
2014-05-22 22:13:20 +00:00
ld b, a
srl b
2014-08-09 05:39:13 +00:00
ld a, [H_PRODUCT + 3]
2014-05-22 22:13:20 +00:00
rr a
srl b
rr a
2014-08-09 05:39:13 +00:00
ld [H_PRODUCT + 3], a
2014-05-22 22:13:20 +00:00
ld a, b
2014-08-09 05:39:13 +00:00
ld [H_PRODUCT + 2], a
.doDivide
ld a, [H_PRODUCT + 2]
ld [H_DIVIDEND], a
ld a, [H_PRODUCT + 3]
ld [H_DIVIDEND + 1], a
2014-05-22 22:13:20 +00:00
ld a, $2
ld b, a
2014-08-09 05:39:13 +00:00
call Divide ; divide (current HP * 48) by max HP
ld a, [H_QUOTIENT + 3]
; set variables for DrawHPBar
2014-05-22 22:13:20 +00:00
ld e, a
ld a, $6
ld d, a
ld c, a
2014-08-09 05:39:13 +00:00
.drawHPBar
2014-05-22 22:13:20 +00:00
xor a
2015-02-08 06:18:42 +00:00
ld [wHPBarType], a
2015-07-18 20:52:03 +00:00
coord hl, 2, 2
2014-05-22 22:13:20 +00:00
call DrawHPBar
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2015-08-12 09:16:56 +00:00
ld hl, wEnemyHPBarColor
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
GetBattleHealthBarColor:
2014-05-22 22:13:20 +00:00
ld b, [hl]
call GetHealthBarColor
ld a, [hl]
cp b
ret z
2015-08-12 09:16:56 +00:00
ld b, SET_PAL_BATTLE
jp RunPaletteCommand
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
; center's mon's name on the battle screen
; if the name is 1 or 2 letters long, it is printed 2 spaces more to the right than usual
; (i.e. for names longer than 4 letters)
; if the name is 3 or 4 letters long, it is printed 1 space more to the right than usual
; (i.e. for names longer than 4 letters)
2016-06-12 00:24:04 +00:00
CenterMonName:
2014-05-22 22:13:20 +00:00
push de
inc hl
inc hl
ld b, $2
2014-08-09 05:39:13 +00:00
.loop
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
2015-08-05 21:20:29 +00:00
cp "@"
2014-08-09 05:39:13 +00:00
jr z, .done
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
2015-08-05 21:20:29 +00:00
cp "@"
2014-08-09 05:39:13 +00:00
jr z, .done
2014-05-22 22:13:20 +00:00
dec hl
dec b
2014-08-09 05:39:13 +00:00
jr nz, .loop
.done
2014-05-22 22:13:20 +00:00
pop de
ret
2016-06-12 00:24:04 +00:00
DisplayBattleMenu:
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1 ; restore saved screen
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2014-05-22 22:13:20 +00:00
and a
jr nz, .nonstandardbattle
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
call PrintEmptyString
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
.nonstandardbattle
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2015-02-07 20:27:36 +00:00
ld a, BATTLE_MENU_TEMPLATE
2014-05-22 22:13:20 +00:00
jr nz, .menuselected
2015-02-07 20:27:36 +00:00
ld a, SAFARI_BATTLE_MENU_TEMPLATE
2014-05-22 22:13:20 +00:00
.menuselected
2015-02-07 10:43:08 +00:00
ld [wTextBoxID], a
2014-05-22 22:13:20 +00:00
call DisplayTextBoxID
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
jp nz, .handleBattleMenuInput ; handle menu input if it's not the old man tutorial
; the following happens for the old man tutorial
ld hl, wPlayerName
2015-08-31 02:38:41 +00:00
ld de, wGrassRate
ld bc, NAME_LENGTH
2014-05-22 22:13:20 +00:00
call CopyData ; temporarily save the player name in unused space,
; which is supposed to get overwritten when entering a
; map with wild Pokémon. Due to an oversight, the data
2014-05-22 22:13:20 +00:00
; may not get overwritten (cinnabar) and the infamous
; Missingno. glitch can show up.
2014-08-09 05:39:13 +00:00
ld hl, .oldManName
ld de, wPlayerName
ld bc, NAME_LENGTH
2014-05-22 22:13:20 +00:00
call CopyData
; the following simulates the keystrokes by drawing menus on screen
2015-07-18 20:52:03 +00:00
coord hl, 9, 14
2014-05-22 22:13:20 +00:00
ld [hl], "▶"
ld c, 80
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-08-05 21:20:29 +00:00
ld [hl], " "
2015-07-18 20:52:03 +00:00
coord hl, 9, 16
2014-05-22 22:13:20 +00:00
ld [hl], "▶"
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
2016-07-18 06:17:03 +00:00
ld [hl], "▷"
2014-08-09 05:39:13 +00:00
ld a, $2 ; select the "ITEM" menu
jp .upperLeftMenuItemWasNotSelected
.oldManName
2014-05-22 22:13:20 +00:00
db "OLD MAN@"
2014-08-09 05:39:13 +00:00
.handleBattleMenuInput
2015-07-16 03:04:58 +00:00
ld a, [wBattleAndStartSavedMenuItem]
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
ld [wLastMenuItem], a
sub 2 ; check if the cursor is in the left column
jr c, .leftColumn
; cursor is in the right column
ld [wCurrentMenuItem], a
ld [wLastMenuItem], a
jr .rightColumn
.leftColumn ; put cursor in left column of menu
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-05-22 22:13:20 +00:00
ld a, " "
2014-08-09 05:39:13 +00:00
jr z, .safariLeftColumn
; put cursor in left column for normal battle menu (i.e. when it's not a Safari battle)
Coorda 15, 14 ; clear upper cursor position in right column
Coorda 15, 16 ; clear lower cursor position in right column
ld b, $9 ; top menu item X
jr .leftColumn_WaitForInput
.safariLeftColumn
Coorda 13, 14
Coorda 13, 16
2015-07-18 20:52:03 +00:00
coord hl, 7, 14
2015-08-31 02:38:41 +00:00
ld de, wNumSafariBalls
2015-07-28 01:48:44 +00:00
lb bc, 1, 2
2014-05-22 22:13:20 +00:00
call PrintNumber
2014-08-09 05:39:13 +00:00
ld b, $1 ; top menu item X
.leftColumn_WaitForInput
ld hl, wTopMenuItemY
2014-05-22 22:13:20 +00:00
ld a, $e
2014-08-09 05:39:13 +00:00
ld [hli], a ; wTopMenuItemY
2014-05-22 22:13:20 +00:00
ld a, b
2014-08-09 05:39:13 +00:00
ld [hli], a ; wTopMenuItemX
2014-05-22 22:13:20 +00:00
inc hl
inc hl
ld a, $1
2014-08-09 05:39:13 +00:00
ld [hli], a ; wMaxMenuItem
ld [hl], D_RIGHT | A_BUTTON ; wMenuWatchedKeys
2014-05-22 22:13:20 +00:00
call HandleMenuInput
2014-08-09 05:39:13 +00:00
bit 4, a ; check if right was pressed
jr nz, .rightColumn
jr .AButtonPressed ; the A button was pressed
.rightColumn ; put cursor in right column of menu
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-05-22 22:13:20 +00:00
ld a, " "
2014-08-09 05:39:13 +00:00
jr z, .safariRightColumn
; put cursor in right column for normal battle menu (i.e. when it's not a Safari battle)
Coorda 9, 14 ; clear upper cursor position in left column
Coorda 9, 16 ; clear lower cursor position in left column
ld b, $f ; top menu item X
jr .rightColumn_WaitForInput
.safariRightColumn
Coorda 1, 14 ; clear upper cursor position in left column
Coorda 1, 16 ; clear lower cursor position in left column
2015-07-18 20:52:03 +00:00
coord hl, 7, 14
2015-08-31 02:38:41 +00:00
ld de, wNumSafariBalls
2015-07-28 01:48:44 +00:00
lb bc, 1, 2
2014-05-22 22:13:20 +00:00
call PrintNumber
2014-08-09 05:39:13 +00:00
ld b, $d ; top menu item X
.rightColumn_WaitForInput
ld hl, wTopMenuItemY
2014-05-22 22:13:20 +00:00
ld a, $e
2014-08-09 05:39:13 +00:00
ld [hli], a ; wTopMenuItemY
2014-05-22 22:13:20 +00:00
ld a, b
2014-08-09 05:39:13 +00:00
ld [hli], a ; wTopMenuItemX
2014-05-22 22:13:20 +00:00
inc hl
inc hl
ld a, $1
2014-08-09 05:39:13 +00:00
ld [hli], a ; wMaxMenuItem
ld a, D_LEFT | A_BUTTON
ld [hli], a ; wMenuWatchedKeys
2014-05-22 22:13:20 +00:00
call HandleMenuInput
2014-08-09 05:39:13 +00:00
bit 5, a ; check if left was pressed
jr nz, .leftColumn ; if left was pressed, jump
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
add $2 ; if we're in the right column, the actual id is +2
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
.AButtonPressed
2014-05-22 22:13:20 +00:00
call PlaceUnfilledArrowMenuCursor
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2015-07-16 03:04:58 +00:00
ld [wBattleAndStartSavedMenuItem], a
2014-08-09 05:39:13 +00:00
jr z, .handleMenuSelection
; not Safari battle
; swap the IDs of the item menu and party menu (this is probably because they swapped the positions
; of these menu items in first generation English versions)
2014-08-09 05:39:13 +00:00
cp $1 ; was the item menu selected?
jr nz, .notItemMenu
; item menu was selected
inc a ; increment a to 2
jr .handleMenuSelection
.notItemMenu
cp $2 ; was the party menu selected?
jr nz, .handleMenuSelection
; party menu selected
dec a ; decrement a to 1
.handleMenuSelection
and a
jr nz, .upperLeftMenuItemWasNotSelected
; the upper left menu item was selected
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-08-09 05:39:13 +00:00
jr z, .throwSafariBallWasSelected
; the "FIGHT" menu was selected
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wNumRunAttempts], a
jp LoadScreenTilesFromBuffer1 ; restore saved screen and return
.throwSafariBallWasSelected
2014-05-22 22:13:20 +00:00
ld a, SAFARI_BALL
ld [wcf91], a
jr UseBagItem
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
.upperLeftMenuItemWasNotSelected ; a menu item other than the upper left item was selected
2014-05-22 22:13:20 +00:00
cp $2
jp nz, PartyMenuOrRockOrRun
2014-08-09 05:39:13 +00:00
; either the bag (normal battle) or bait (safari battle) was selected
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-08-09 05:39:13 +00:00
jr nz, .notLinkBattle
2014-08-09 05:39:13 +00:00
; can't use items in link battles
2014-05-22 22:13:20 +00:00
ld hl, ItemsCantBeUsedHereText
call PrintText
2014-08-09 05:39:13 +00:00
jp DisplayBattleMenu
2014-08-09 05:39:13 +00:00
.notLinkBattle
call SaveScreenTilesToBuffer2
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
jr nz, BagWasSelected
2014-08-09 05:39:13 +00:00
; bait was selected
2014-05-22 22:13:20 +00:00
ld a, SAFARI_BAIT
ld [wcf91], a
jr UseBagItem
BagWasSelected:
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2014-08-09 05:39:13 +00:00
and a ; is it a normal battle?
jr nz, .next
2014-08-09 05:39:13 +00:00
; normal battle
call DrawHUDsAndHPBars
.next
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2014-08-09 05:39:13 +00:00
dec a ; is it the old man tutorial?
jr nz, DisplayPlayerBag ; no, it is a normal battle
2014-05-22 22:13:20 +00:00
ld hl, OldManItemList
ld a, l
2015-07-15 06:16:06 +00:00
ld [wListPointer], a
2014-05-22 22:13:20 +00:00
ld a, h
2015-07-15 06:16:06 +00:00
ld [wListPointer + 1], a
jr DisplayBagMenu
2014-05-22 22:13:20 +00:00
OldManItemList:
db 1 ; # items
db POKE_BALL, 50
db -1
2014-05-22 22:13:20 +00:00
DisplayPlayerBag:
; get the pointer to player's bag when in a normal battle
2014-08-09 05:39:13 +00:00
ld hl, wNumBagItems
2014-05-22 22:13:20 +00:00
ld a, l
2015-07-15 06:16:06 +00:00
ld [wListPointer], a
2014-05-22 22:13:20 +00:00
ld a, h
2015-07-15 06:16:06 +00:00
ld [wListPointer + 1], a
DisplayBagMenu:
2014-05-22 22:13:20 +00:00
xor a
2015-07-13 06:00:48 +00:00
ld [wPrintItemPrices], a
2014-08-09 05:39:13 +00:00
ld a, ITEMLISTMENU
ld [wListMenuID], a
2015-07-16 03:04:58 +00:00
ld a, [wBagSavedMenuItem]
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
2014-05-22 22:13:20 +00:00
call DisplayListMenuID
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2015-07-16 03:04:58 +00:00
ld [wBagSavedMenuItem], a
2014-05-22 22:13:20 +00:00
ld a, $0
2015-07-13 07:32:03 +00:00
ld [wMenuWatchMovingOutOfBounds], a
2014-08-09 05:39:13 +00:00
ld [wMenuItemToSwap], a
jp c, DisplayBattleMenu ; go back to battle menu if an item was not selected
UseBagItem:
; either use an item from the bag or use a safari zone item
ld a, [wcf91]
ld [wd11e], a
2014-05-22 22:13:20 +00:00
call GetItemName
call CopyStringToCF4B ; copy name
xor a
2015-07-26 02:26:54 +00:00
ld [wPseudoItemID], a
2014-05-22 22:13:20 +00:00
call UseItem
2014-08-09 05:39:13 +00:00
call LoadHudTilePatterns
2014-05-23 22:34:35 +00:00
call ClearSprites
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-08-09 05:39:13 +00:00
jr z, .checkIfMonCaptured
2015-07-15 06:16:06 +00:00
ld a, [wActionResultOrTookBattleTurn]
2014-08-09 05:39:13 +00:00
and a ; was the item used successfully?
jp z, BagWasSelected ; if not, go back to the bag menu
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus1]
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, a ; is the player using a multi-turn move like wrap?
2014-08-09 05:39:13 +00:00
jr z, .checkIfMonCaptured
ld hl, wPlayerNumAttacksLeft
2014-05-22 22:13:20 +00:00
dec [hl]
2014-08-09 05:39:13 +00:00
jr nz, .checkIfMonCaptured
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2017-12-29 23:59:48 +00:00
res USING_TRAPPING_MOVE, [hl] ; not using multi-turn move any more
2014-08-09 05:39:13 +00:00
.checkIfMonCaptured
2015-07-25 03:27:59 +00:00
ld a, [wCapturedMonSpecies]
2014-08-09 05:39:13 +00:00
and a ; was the enemy mon captured with a ball?
jr nz, .returnAfterCapturingMon
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-08-09 05:39:13 +00:00
jr z, .returnAfterUsingItem_NoCapture
; not a safari battle
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2014-08-09 05:39:13 +00:00
call DrawHUDsAndHPBars
2014-05-22 22:13:20 +00:00
call Delay3
2014-08-09 05:39:13 +00:00
.returnAfterUsingItem_NoCapture
2014-05-22 22:13:20 +00:00
call GBPalNormal
2014-08-09 05:39:13 +00:00
and a ; reset carry
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
.returnAfterCapturingMon
2014-05-22 22:13:20 +00:00
call GBPalNormal
xor a
2015-07-25 03:27:59 +00:00
ld [wCapturedMonSpecies], a
2014-05-22 22:13:20 +00:00
ld a, $2
2014-08-09 05:39:13 +00:00
ld [wBattleResult], a
scf ; set carry
2014-05-22 22:13:20 +00:00
ret
ItemsCantBeUsedHereText:
2014-05-22 22:13:20 +00:00
TX_FAR _ItemsCantBeUsedHereText
db "@"
PartyMenuOrRockOrRun:
2014-08-09 05:39:13 +00:00
dec a ; was Run selected?
jp nz, BattleMenu_RunWasSelected
; party menu or rock was selected
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer2
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2015-08-30 06:35:58 +00:00
cp BATTLE_TYPE_SAFARI
2014-08-09 05:39:13 +00:00
jr nz, .partyMenuWasSelected
; safari battle
2014-05-22 22:13:20 +00:00
ld a, SAFARI_ROCK
ld [wcf91], a
jp UseBagItem
2014-08-09 05:39:13 +00:00
.partyMenuWasSelected
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
xor a ; NORMAL_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
2014-08-09 05:39:13 +00:00
ld [wMenuItemToSwap], a
2014-05-22 22:13:20 +00:00
call DisplayPartyMenu
2014-08-09 05:39:13 +00:00
.checkIfPartyMonWasSelected
jp nc, .partyMonWasSelected ; if a party mon was selected, jump, else we quit the party menu
.quitPartyMenu
2014-05-23 22:34:35 +00:00
call ClearSprites
2014-05-22 22:13:20 +00:00
call GBPalWhiteOut
2014-08-09 05:39:13 +00:00
call LoadHudTilePatterns
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer2
2015-08-12 09:16:56 +00:00
call RunDefaultPaletteCommand
2014-05-22 22:13:20 +00:00
call GBPalNormal
2014-08-09 05:39:13 +00:00
jp DisplayBattleMenu
.partyMonDeselected
2015-07-18 20:52:03 +00:00
coord hl, 11, 11
2015-08-10 04:56:20 +00:00
ld bc, 6 * SCREEN_WIDTH + 9
2015-08-05 21:20:29 +00:00
ld a, " "
2014-05-22 22:13:20 +00:00
call FillMemory
xor a ; NORMAL_PARTY_MENU
ld [wPartyMenuTypeOrMessageID], a
2014-05-22 22:13:20 +00:00
call GoBackToPartyMenu
2014-08-09 05:39:13 +00:00
jr .checkIfPartyMonWasSelected
.partyMonWasSelected
2015-02-07 20:27:36 +00:00
ld a, SWITCH_STATS_CANCEL_MENU_TEMPLATE
2015-02-07 10:43:08 +00:00
ld [wTextBoxID], a
2014-05-22 22:13:20 +00:00
call DisplayTextBoxID
2014-08-09 05:39:13 +00:00
ld hl, wTopMenuItemY
2014-05-22 22:13:20 +00:00
ld a, $c
2014-08-09 05:39:13 +00:00
ld [hli], a ; wTopMenuItemY
ld [hli], a ; wTopMenuItemX
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [hli], a ; wCurrentMenuItem
2014-05-22 22:13:20 +00:00
inc hl
ld a, $2
2014-08-09 05:39:13 +00:00
ld [hli], a ; wMaxMenuItem
ld a, B_BUTTON | A_BUTTON
ld [hli], a ; wMenuWatchedKeys
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [hl], a ; wLastMenuItem
2014-05-22 22:13:20 +00:00
call HandleMenuInput
2014-08-09 05:39:13 +00:00
bit 1, a ; was A pressed?
jr nz, .partyMonDeselected ; if B was pressed, jump
; A was pressed
2014-05-22 22:13:20 +00:00
call PlaceUnfilledArrowMenuCursor
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
cp $2 ; was Cancel selected?
jr z, .quitPartyMenu ; if so, quit the party menu entirely
and a ; was Switch selected?
jr z, .switchMon ; if so, jump
; Stats was selected
2015-07-16 03:04:58 +00:00
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
2014-08-09 05:39:13 +00:00
ld hl, wPartyMon1
2014-05-23 22:34:35 +00:00
call ClearSprites
2014-08-09 05:39:13 +00:00
; display the two status screens
predef StatusScreen
predef StatusScreen2
2014-08-09 05:39:13 +00:00
; now we need to reload the enemy mon pic
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus2]
2017-12-29 23:59:48 +00:00
bit HAS_SUBSTITUTE_UP, a ; does the enemy mon have a substitute?
2014-05-22 22:13:20 +00:00
ld hl, AnimationSubstitute
2014-08-09 05:39:13 +00:00
jr nz, .doEnemyMonAnimation
; enemy mon doesn't have substitute
2015-07-12 22:51:04 +00:00
ld a, [wEnemyMonMinimized]
2014-08-09 05:39:13 +00:00
and a ; has the enemy mon used Minimise?
2014-05-22 22:13:20 +00:00
ld hl, AnimationMinimizeMon
2014-08-09 05:39:13 +00:00
jr nz, .doEnemyMonAnimation
; enemy mon is not minimised
ld a, [wEnemyMonSpecies]
ld [wcf91], a
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
2014-05-29 08:31:46 +00:00
ld de, vFrontPic
2014-05-22 22:13:20 +00:00
call LoadMonFrontSprite
2014-08-09 05:39:13 +00:00
jr .enemyMonPicReloaded
.doEnemyMonAnimation
2014-05-22 22:13:20 +00:00
ld b, BANK(AnimationSubstitute) ; BANK(AnimationMinimizeMon)
call Bankswitch
2014-08-09 05:39:13 +00:00
.enemyMonPicReloaded ; enemy mon pic has been reloaded, so return to the party menu
jp .partyMenuWasSelected
.switchMon
ld a, [wPlayerMonNumber]
2014-05-22 22:13:20 +00:00
ld d, a
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
cp d ; check if the mon to switch to is already out
jr nz, .notAlreadyOut
; mon is already out
2014-05-22 22:13:20 +00:00
ld hl, AlreadyOutText
call PrintText
2014-08-09 05:39:13 +00:00
jp .partyMonDeselected
.notAlreadyOut
call HasMonFainted
jp z, .partyMonDeselected ; can't switch to fainted mon
2014-05-22 22:13:20 +00:00
ld a, $1
2015-07-15 06:16:06 +00:00
ld [wActionResultOrTookBattleTurn], a
2014-05-22 22:13:20 +00:00
call GBPalWhiteOut
2014-05-23 22:34:35 +00:00
call ClearSprites
2014-08-09 05:39:13 +00:00
call LoadHudTilePatterns
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-08-12 09:16:56 +00:00
call RunDefaultPaletteCommand
2014-05-22 22:13:20 +00:00
call GBPalNormal
2014-08-09 05:39:13 +00:00
; fall through to SwitchPlayerMon
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
SwitchPlayerMon:
2014-05-22 22:13:20 +00:00
callab RetreatMon
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
2014-08-09 05:39:13 +00:00
call AnimateRetreatingPlayerMon
ld a, [wWhichPokemon]
ld [wPlayerMonNumber], a
2014-05-22 22:13:20 +00:00
ld c, a
2015-07-20 03:45:34 +00:00
ld b, FLAG_SET
2014-05-22 22:13:20 +00:00
push bc
2014-08-09 05:39:13 +00:00
ld hl, wPartyGainExpFlags
predef FlagActionPredef
2014-05-22 22:13:20 +00:00
pop bc
2014-08-09 05:39:13 +00:00
ld hl, wPartyFoughtCurrentEnemyFlags
predef FlagActionPredef
2014-08-09 05:39:13 +00:00
call LoadBattleMonFromParty
call SendOutMon
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
ld a, $2
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
2014-05-22 22:13:20 +00:00
and a
ret
2016-06-12 00:24:04 +00:00
AlreadyOutText:
2014-05-22 22:13:20 +00:00
TX_FAR _AlreadyOutText
db "@"
2016-06-12 00:24:04 +00:00
BattleMenu_RunWasSelected:
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
ld a, $3
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
ld hl, wBattleMonSpeed
ld de, wEnemyMonSpeed
2014-08-09 05:39:13 +00:00
call TryRunningFromBattle
2015-07-25 03:27:59 +00:00
ld a, 0
ld [wForcePlayerToChooseMon], a
2014-05-22 22:13:20 +00:00
ret c
2015-07-15 06:16:06 +00:00
ld a, [wActionResultOrTookBattleTurn]
2014-05-22 22:13:20 +00:00
and a
2015-07-15 06:16:06 +00:00
ret nz ; return if the player couldn't escape
2014-08-09 05:39:13 +00:00
jp DisplayBattleMenu
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
MoveSelectionMenu:
2014-05-22 22:13:20 +00:00
ld a, [wMoveMenuType]
dec a
jr z, .mimicmenu
dec a
jr z, .relearnmenu
jr .regularmenu
.loadmoves
2015-02-08 08:17:03 +00:00
ld de, wMoves
ld bc, NUM_MOVES
2014-05-22 22:13:20 +00:00
call CopyData
2015-02-08 08:17:03 +00:00
callab FormatMovesString
2014-05-22 22:13:20 +00:00
ret
.writemoves
2015-02-08 08:17:03 +00:00
ld de, wMovesString
2015-02-08 00:24:16 +00:00
ld a, [hFlags_0xFFF6]
2014-05-22 22:13:20 +00:00
set 2, a
2015-02-08 00:24:16 +00:00
ld [hFlags_0xFFF6], a
2014-05-22 22:13:20 +00:00
call PlaceString
2015-02-08 00:24:16 +00:00
ld a, [hFlags_0xFFF6]
2014-05-22 22:13:20 +00:00
res 2, a
2015-02-08 00:24:16 +00:00
ld [hFlags_0xFFF6], a
2014-05-22 22:13:20 +00:00
ret
.regularmenu
call AnyMoveToSelect
2014-05-22 22:13:20 +00:00
ret z
ld hl, wBattleMonMoves
2014-05-22 22:13:20 +00:00
call .loadmoves
2015-07-18 20:52:03 +00:00
coord hl, 4, 12
2016-06-12 04:30:05 +00:00
ld b, 4
ld c, 14
di ; out of pure coincidence, it is possible for vblank to occur between the di and ei
; so it is necessary to put the di ei block to not cause tearing
2014-05-22 22:13:20 +00:00
call TextBoxBorder
2015-07-18 20:52:03 +00:00
coord hl, 4, 12
2014-05-22 22:13:20 +00:00
ld [hl], $7a
2015-07-18 20:52:03 +00:00
coord hl, 10, 12
2014-05-22 22:13:20 +00:00
ld [hl], $7e
ei
2015-07-18 20:52:03 +00:00
coord hl, 6, 13
2014-05-22 22:13:20 +00:00
call .writemoves
ld b, $5
ld a, $c
jr .menuset
.mimicmenu
ld hl, wEnemyMonMoves
2014-05-22 22:13:20 +00:00
call .loadmoves
2015-07-18 20:52:03 +00:00
coord hl, 0, 7
2016-06-12 04:30:05 +00:00
ld b, 4
ld c, 14
2014-05-22 22:13:20 +00:00
call TextBoxBorder
2015-07-18 20:52:03 +00:00
coord hl, 2, 8
2014-05-22 22:13:20 +00:00
call .writemoves
ld b, $1
ld a, $7
jr .menuset
.relearnmenu
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld hl, wPartyMon1Moves
2015-08-05 21:20:29 +00:00
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
call .loadmoves
2015-07-18 20:52:03 +00:00
coord hl, 4, 7
2016-06-12 04:30:05 +00:00
ld b, 4
ld c, 14
2014-05-22 22:13:20 +00:00
call TextBoxBorder
2015-07-18 20:52:03 +00:00
coord hl, 6, 8
2014-05-22 22:13:20 +00:00
call .writemoves
ld b, $5
ld a, $7
.menuset
2014-08-09 05:39:13 +00:00
ld hl, wTopMenuItemY
2015-07-15 06:16:06 +00:00
ld [hli], a ; wTopMenuItemY
2014-05-22 22:13:20 +00:00
ld a, b
2015-07-15 06:16:06 +00:00
ld [hli], a ; wTopMenuItemX
2014-05-22 22:13:20 +00:00
ld a, [wMoveMenuType]
cp $1
jr z, .selectedmoveknown
ld a, $1
jr nc, .selectedmoveknown
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMoveListIndex]
2014-05-22 22:13:20 +00:00
inc a
.selectedmoveknown
2015-07-15 06:16:06 +00:00
ld [hli], a ; wCurrentMenuItem
2014-05-22 22:13:20 +00:00
inc hl ; wTileBehindCursor untouched
2015-07-15 06:16:06 +00:00
ld a, [wNumMovesMinusOne]
2014-05-22 22:13:20 +00:00
inc a
inc a
2015-07-15 06:16:06 +00:00
ld [hli], a ; wMaxMenuItem
2014-05-22 22:13:20 +00:00
ld a, [wMoveMenuType]
dec a
2015-07-15 06:16:06 +00:00
ld b, D_UP | D_DOWN | A_BUTTON
2014-05-22 22:13:20 +00:00
jr z, .matchedkeyspicked
dec a
2015-07-15 06:16:06 +00:00
ld b, D_UP | D_DOWN | A_BUTTON | B_BUTTON
2014-05-22 22:13:20 +00:00
jr z, .matchedkeyspicked
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
jr z, .matchedkeyspicked
2015-08-31 02:38:41 +00:00
ld a, [wFlags_D733]
2015-08-14 02:13:47 +00:00
bit BIT_TEST_BATTLE, a
2015-07-15 06:16:06 +00:00
ld b, D_UP | D_DOWN | A_BUTTON | B_BUTTON | SELECT
2014-05-22 22:13:20 +00:00
jr z, .matchedkeyspicked
ld b, $ff
.matchedkeyspicked
ld a, b
2015-07-15 06:16:06 +00:00
ld [hli], a ; wMenuWatchedKeys
2014-05-22 22:13:20 +00:00
ld a, [wMoveMenuType]
cp $1
jr z, .movelistindex1
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMoveListIndex]
2014-05-22 22:13:20 +00:00
inc a
.movelistindex1
2014-08-09 05:39:13 +00:00
ld [hl], a
; fallthrough
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
SelectMenuItem:
2014-05-22 22:13:20 +00:00
ld a, [wMoveMenuType]
and a
jr z, .battleselect
dec a
jr nz, .select
2015-07-18 20:52:03 +00:00
coord hl, 1, 14
2014-08-09 05:39:13 +00:00
ld de, WhichTechniqueString
2014-05-22 22:13:20 +00:00
call PlaceString
jr .select
.battleselect
2015-08-31 02:38:41 +00:00
ld a, [wFlags_D733]
2015-08-14 02:13:47 +00:00
bit BIT_TEST_BATTLE, a
2014-05-22 22:13:20 +00:00
jr nz, .select
call PrintMenuItem
2014-08-09 05:39:13 +00:00
ld a, [wMenuItemToSwap]
2014-05-22 22:13:20 +00:00
and a
jr z, .select
2015-07-18 20:52:03 +00:00
coord hl, 5, 13
2014-05-22 22:13:20 +00:00
dec a
2015-08-05 21:20:29 +00:00
ld bc, SCREEN_WIDTH
2014-05-22 22:13:20 +00:00
call AddNTimes
2016-07-18 06:17:03 +00:00
ld [hl], "▷"
2014-05-22 22:13:20 +00:00
.select
2015-02-08 00:24:16 +00:00
ld hl, hFlags_0xFFF6
2014-05-22 22:13:20 +00:00
set 1, [hl]
call HandleMenuInput
2015-02-08 00:24:16 +00:00
ld hl, hFlags_0xFFF6
2014-05-22 22:13:20 +00:00
res 1, [hl]
bit 6, a
2016-06-12 04:30:05 +00:00
jp nz, SelectMenuItem_CursorUp ; up
2014-05-22 22:13:20 +00:00
bit 7, a
2016-06-12 04:30:05 +00:00
jp nz, SelectMenuItem_CursorDown ; down
2014-05-22 22:13:20 +00:00
bit 2, a
2014-08-09 05:39:13 +00:00
jp nz, SwapMovesInMenu ; select
2014-05-22 22:13:20 +00:00
bit 1, a ; B, but was it reset above?
push af
xor a
2014-08-09 05:39:13 +00:00
ld [wMenuItemToSwap], a
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
2014-05-22 22:13:20 +00:00
ld b, a
ld a, [wMoveMenuType]
dec a ; if not mimic
2016-06-12 04:30:05 +00:00
jr nz, .notB
2014-05-22 22:13:20 +00:00
pop af
ret
2016-06-12 04:30:05 +00:00
.notB
2014-05-22 22:13:20 +00:00
dec a
ld a, b
2014-08-09 05:39:13 +00:00
ld [wPlayerMoveListIndex], a
2014-05-22 22:13:20 +00:00
jr nz, .moveselected
pop af
ret
.moveselected
pop af
ret nz
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonPP
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
add hl, bc
ld a, [hl]
and $3f
2016-06-12 04:30:05 +00:00
jr z, .noPP
2015-08-31 02:38:41 +00:00
ld a, [wPlayerDisabledMove]
2014-05-22 22:13:20 +00:00
swap a
and $f
dec a
cp c
jr z, .disabled
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus3]
2014-05-22 22:13:20 +00:00
bit 3, a ; transformed
jr nz, .dummy ; game freak derp
.dummy
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
ld hl, wBattleMonMoves
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
add hl, bc
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [wPlayerSelectedMove], a
2014-05-22 22:13:20 +00:00
xor a
ret
.disabled
ld hl, MoveDisabledText
jr .print
2016-06-12 04:30:05 +00:00
.noPP
2014-05-22 22:13:20 +00:00
ld hl, MoveNoPPText
.print
call PrintText
call LoadScreenTilesFromBuffer1
jp MoveSelectionMenu
2016-06-12 00:24:04 +00:00
MoveNoPPText:
2014-05-22 22:13:20 +00:00
TX_FAR _MoveNoPPText
db "@"
2016-06-12 00:24:04 +00:00
MoveDisabledText:
2014-05-22 22:13:20 +00:00
TX_FAR _MoveDisabledText
db "@"
2016-06-12 00:24:04 +00:00
WhichTechniqueString:
2014-05-22 22:13:20 +00:00
db "WHICH TECHNIQUE?@"
2016-06-12 04:30:05 +00:00
SelectMenuItem_CursorUp:
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
and a
jp nz, SelectMenuItem
2014-05-22 22:13:20 +00:00
call EraseMenuCursor
2015-07-15 06:16:06 +00:00
ld a, [wNumMovesMinusOne]
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
jp SelectMenuItem
2014-05-22 22:13:20 +00:00
2016-06-12 04:30:05 +00:00
SelectMenuItem_CursorDown:
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
ld b, a
2015-07-15 06:16:06 +00:00
ld a, [wNumMovesMinusOne]
2014-05-22 22:13:20 +00:00
inc a
inc a
cp b
jp nz, SelectMenuItem
2014-05-22 22:13:20 +00:00
call EraseMenuCursor
ld a, $1
2014-08-09 05:39:13 +00:00
ld [wCurrentMenuItem], a
jp SelectMenuItem
2016-06-12 00:24:04 +00:00
AnyMoveToSelect:
; return z and Struggle as the selected move if all moves have 0 PP and/or are disabled
2014-08-09 05:39:13 +00:00
ld a, STRUGGLE
ld [wPlayerSelectedMove], a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerDisabledMove]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonPP
2016-06-12 04:30:05 +00:00
jr nz, .handleDisabledMove
2014-05-22 22:13:20 +00:00
ld a, [hli]
or [hl]
inc hl
or [hl]
inc hl
or [hl]
and $3f
ret nz
2016-06-12 04:30:05 +00:00
jr .noMovesLeft
.handleDisabledMove
2014-05-22 22:13:20 +00:00
swap a
2016-06-12 04:30:05 +00:00
and $f ; get disabled move
2014-05-22 22:13:20 +00:00
ld b, a
2016-06-12 04:30:05 +00:00
ld d, NUM_MOVES + 1
2014-05-22 22:13:20 +00:00
xor a
2016-06-12 04:30:05 +00:00
.handleDisabledMovePPLoop
2014-05-22 22:13:20 +00:00
dec d
2016-06-12 04:30:05 +00:00
jr z, .allMovesChecked
ld c, [hl] ; get move PP
2014-05-22 22:13:20 +00:00
inc hl
2016-06-12 04:30:05 +00:00
dec b ; is this the disabled move?
jr z, .handleDisabledMovePPLoop ; if so, ignore its PP value
2014-05-22 22:13:20 +00:00
or c
2016-06-12 04:30:05 +00:00
jr .handleDisabledMovePPLoop
.allMovesChecked
and a ; any PP left?
ret nz ; return if a move has PP left
.noMovesLeft
2014-05-22 22:13:20 +00:00
ld hl, NoMovesLeftText
call PrintText
ld c, 60
2014-05-22 22:13:20 +00:00
call DelayFrames
xor a
ret
2016-06-12 00:24:04 +00:00
NoMovesLeftText:
2014-05-22 22:13:20 +00:00
TX_FAR _NoMovesLeftText
db "@"
2016-06-12 00:24:04 +00:00
SwapMovesInMenu:
2014-08-09 05:39:13 +00:00
ld a, [wMenuItemToSwap]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .noMenuItemSelected
ld hl, wBattleMonMoves
2014-08-09 05:39:13 +00:00
call .swapBytes ; swap moves
ld hl, wBattleMonPP
call .swapBytes ; swap move PP
; update the index of the disabled move if necessary
2015-08-31 02:38:41 +00:00
ld hl, wPlayerDisabledMove
2014-05-22 22:13:20 +00:00
ld a, [hl]
swap a
and $f
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
cp b
2014-08-09 05:39:13 +00:00
jr nz, .next
2014-05-22 22:13:20 +00:00
ld a, [hl]
and $f
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wMenuItemToSwap]
2014-05-22 22:13:20 +00:00
swap a
add b
ld [hl], a
2014-08-09 05:39:13 +00:00
jr .swapMovesInPartyMon
.next
ld a, [wMenuItemToSwap]
2014-05-22 22:13:20 +00:00
cp b
2014-08-09 05:39:13 +00:00
jr nz, .swapMovesInPartyMon
2014-05-22 22:13:20 +00:00
ld a, [hl]
and $f
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
swap a
add b
ld [hl], a
2014-08-09 05:39:13 +00:00
.swapMovesInPartyMon
ld hl, wPartyMon1Moves
ld a, [wPlayerMonNumber]
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
push hl
2014-08-09 05:39:13 +00:00
call .swapBytes ; swap moves
2014-05-22 22:13:20 +00:00
pop hl
2015-08-05 21:20:29 +00:00
ld bc, wPartyMon1PP - wPartyMon1Moves
2014-05-22 22:13:20 +00:00
add hl, bc
2014-08-09 05:39:13 +00:00
call .swapBytes ; swap move PP
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wMenuItemToSwap], a ; deselect the item
2014-05-22 22:13:20 +00:00
jp MoveSelectionMenu
2014-08-09 05:39:13 +00:00
.swapBytes
2014-05-22 22:13:20 +00:00
push hl
2014-08-09 05:39:13 +00:00
ld a, [wMenuItemToSwap]
2014-05-22 22:13:20 +00:00
dec a
ld c, a
2014-08-09 05:39:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
ld d, h
ld e, l
pop hl
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
dec a
ld c, a
2014-08-09 05:39:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, [de]
ld b, [hl]
ld [hl], a
ld a, b
ld [de], a
ret
2014-08-09 05:39:13 +00:00
.noMenuItemSelected
ld a, [wCurrentMenuItem]
ld [wMenuItemToSwap], a ; select the current menu item for swapping
2014-05-22 22:13:20 +00:00
jp MoveSelectionMenu
2016-06-12 00:24:04 +00:00
PrintMenuItem:
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2015-07-18 20:52:03 +00:00
coord hl, 0, 8
2016-06-12 04:30:05 +00:00
ld b, 3
ld c, 9
2014-05-22 22:13:20 +00:00
call TextBoxBorder
2015-08-31 02:38:41 +00:00
ld a, [wPlayerDisabledMove]
2014-05-22 22:13:20 +00:00
and a
jr z, .notDisabled
2014-05-22 22:13:20 +00:00
swap a
and $f
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
cp b
jr nz, .notDisabled
2015-07-18 20:52:03 +00:00
coord hl, 1, 10
2014-05-22 22:13:20 +00:00
ld de, DisabledText
call PlaceString
jr .moveDisabled
.notDisabled
2014-08-09 05:39:13 +00:00
ld hl, wCurrentMenuItem
2014-05-22 22:13:20 +00:00
dec [hl]
xor a
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
ld hl, wBattleMonMoves
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0 ; which item in the menu is the cursor pointing to? (0-3)
add hl, bc ; point to the item (move) in memory
2015-06-11 22:41:33 +00:00
ld a, [hl]
ld [wPlayerSelectedMove], a ; update wPlayerSelectedMove even if the move
; isn't actually selected (just pointed to by the cursor)
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMonNumber]
ld [wWhichPokemon], a
2015-07-16 03:04:58 +00:00
ld a, BATTLE_MON_DATA
ld [wMonDataLocation], a
2014-05-22 22:13:20 +00:00
callab GetMaxPP
2014-08-09 05:39:13 +00:00
ld hl, wCurrentMenuItem
2014-05-22 22:13:20 +00:00
ld c, [hl]
inc [hl]
ld b, $0
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonPP
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, [hl]
and $3f
ld [wcd6d], a
2015-06-11 22:41:33 +00:00
; print TYPE/<type> and <curPP>/<maxPP>
2015-07-18 20:52:03 +00:00
coord hl, 1, 9
2014-05-22 22:13:20 +00:00
ld de, TypeText
call PlaceString
2015-07-18 20:52:03 +00:00
coord hl, 7, 11
2014-05-22 22:13:20 +00:00
ld [hl], "/"
2015-07-18 20:52:03 +00:00
coord hl, 5, 9
2014-05-22 22:13:20 +00:00
ld [hl], "/"
2015-07-18 20:52:03 +00:00
coord hl, 5, 11
ld de, wcd6d
2015-07-28 01:48:44 +00:00
lb bc, 1, 2
2014-05-22 22:13:20 +00:00
call PrintNumber
2015-07-18 20:52:03 +00:00
coord hl, 8, 11
2015-08-07 12:20:37 +00:00
ld de, wMaxPP
2015-07-28 01:48:44 +00:00
lb bc, 1, 2
2014-05-22 22:13:20 +00:00
call PrintNumber
2015-06-11 22:41:33 +00:00
call GetCurrentMove
2015-07-18 20:52:03 +00:00
coord hl, 2, 10
2015-02-08 00:24:16 +00:00
predef PrintMoveType
.moveDisabled
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-05-22 22:13:20 +00:00
jp Delay3
2016-06-12 00:24:04 +00:00
DisabledText:
2014-05-22 22:13:20 +00:00
db "disabled!@"
2016-06-12 00:24:04 +00:00
TypeText:
2014-05-22 22:13:20 +00:00
db "TYPE@"
2016-06-12 00:24:04 +00:00
SelectEnemyMove:
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
2015-07-15 06:16:06 +00:00
sub LINK_STATE_BATTLING
2014-05-22 22:13:20 +00:00
jr nz, .noLinkBattle
2014-08-09 05:39:13 +00:00
; link battle
2014-05-22 22:13:20 +00:00
call SaveScreenTilesToBuffer1
2014-08-09 05:39:13 +00:00
call LinkBattleExchangeData
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-02-07 10:43:08 +00:00
ld a, [wSerialExchangeNybbleReceiveData]
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_STRUGGLE
2016-06-12 04:30:05 +00:00
jp z, .linkedOpponentUsedStruggle
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_NO_ACTION
jr z, .unableToSelectMove
2016-10-29 08:44:13 +00:00
cp 4
2014-05-22 22:13:20 +00:00
ret nc
ld [wEnemyMoveListIndex], a
2014-05-22 22:13:20 +00:00
ld c, a
ld hl, wEnemyMonMoves
2016-10-29 08:44:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, [hl]
jr .done
.noLinkBattle
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus2]
2017-12-29 23:59:48 +00:00
and (1 << NEEDS_TO_RECHARGE) | (1 << USING_RAGE) ; need to recharge or using rage
2014-05-22 22:13:20 +00:00
ret nz
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-05-22 22:13:20 +00:00
ld a, [hl]
2017-12-29 23:59:48 +00:00
and (1 << CHARGING_UP) | (1 << THRASHING_ABOUT) ; using a charging move or thrash/petal dance
2014-05-22 22:13:20 +00:00
ret nz
ld a, [wEnemyMonStatus]
2014-05-22 22:13:20 +00:00
and SLP | 1 << FRZ ; sleeping or frozen
ret nz
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus1]
2017-12-29 23:59:48 +00:00
and (1 << USING_TRAPPING_MOVE) | (1 << STORING_ENERGY) ; using a trapping move like wrap or bide
2014-05-22 22:13:20 +00:00
ret nz
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus1]
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, a ; caught in player's trapping move (e.g. wrap)
jr z, .canSelectMove
.unableToSelectMove
2014-05-22 22:13:20 +00:00
ld a, $ff
jr .done
.canSelectMove
ld hl, wEnemyMonMoves+1 ; 2nd enemy move
2014-05-22 22:13:20 +00:00
ld a, [hld]
and a
jr nz, .atLeastTwoMovesAvailable
2015-08-31 02:38:41 +00:00
ld a, [wEnemyDisabledMove]
2014-05-22 22:13:20 +00:00
and a
ld a, STRUGGLE ; struggle if the only move is disabled
jr nz, .done
.atLeastTwoMovesAvailable
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
jr z, .chooseRandomMove ; wild encounter
callab AIEnemyTrainerChooseMoves
.chooseRandomMove
push hl
call BattleRandom
2014-05-22 22:13:20 +00:00
ld b, $1
2015-07-25 03:27:59 +00:00
cp $3f ; select move 1, [0,3e] (63/256 chance)
2014-05-22 22:13:20 +00:00
jr c, .moveChosen
inc hl
inc b
2015-07-25 03:27:59 +00:00
cp $7f ; select move 2, [3f,7e] (64/256 chance)
2014-05-22 22:13:20 +00:00
jr c, .moveChosen
inc hl
inc b
2015-07-25 03:27:59 +00:00
cp $be ; select move 3, [7f,bd] (63/256 chance)
2014-05-22 22:13:20 +00:00
jr c, .moveChosen
inc hl
2015-07-25 03:27:59 +00:00
inc b ; select move 4, [be,ff] (66/256 chance)
2014-05-22 22:13:20 +00:00
.moveChosen
ld a, b
dec a
ld [wEnemyMoveListIndex], a
2015-08-31 02:38:41 +00:00
ld a, [wEnemyDisabledMove]
2014-05-22 22:13:20 +00:00
swap a
and $f
cp b
ld a, [hl]
pop hl
jr z, .chooseRandomMove ; move disabled, try again
and a
jr z, .chooseRandomMove ; move non-existant, try again
.done
ld [wEnemySelectedMove], a
ret
2016-06-12 04:30:05 +00:00
.linkedOpponentUsedStruggle
2014-08-09 05:39:13 +00:00
ld a, STRUGGLE
2014-05-22 22:13:20 +00:00
jr .done
2014-08-09 05:39:13 +00:00
; this appears to exchange data with the other gameboy during link battles
2016-06-12 00:24:04 +00:00
LinkBattleExchangeData:
2014-05-22 22:13:20 +00:00
ld a, $ff
2015-02-07 10:43:08 +00:00
ld [wSerialExchangeNybbleReceiveData], a
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMoveListIndex]
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_RUN ; is the player running from battle?
2015-07-15 06:16:06 +00:00
jr z, .doExchange
ld a, [wActionResultOrTookBattleTurn]
and a ; is the player switching in another mon?
jr nz, .switching
; the player used a move
2014-08-09 05:39:13 +00:00
ld a, [wPlayerSelectedMove]
cp STRUGGLE
2016-10-29 08:44:13 +00:00
ld b, LINKBATTLE_STRUGGLE
2015-07-15 06:16:06 +00:00
jr z, .next
2016-10-29 09:04:48 +00:00
dec b ; LINKBATTLE_NO_ACTION
inc a ; does move equal -1 (i.e. no action)?
2015-07-15 06:16:06 +00:00
jr z, .next
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMoveListIndex]
2015-07-15 06:16:06 +00:00
jr .doExchange
.switching
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
2015-07-15 06:16:06 +00:00
add 4
2014-05-22 22:13:20 +00:00
ld b, a
2015-07-15 06:16:06 +00:00
.next
2014-05-22 22:13:20 +00:00
ld a, b
2015-07-15 06:16:06 +00:00
.doExchange
2015-02-07 10:43:08 +00:00
ld [wSerialExchangeNybbleSendData], a
2014-05-22 22:13:20 +00:00
callab PrintWaitingText
2015-07-15 06:16:06 +00:00
.syncLoop1
2015-02-07 10:43:08 +00:00
call Serial_ExchangeNybble
2014-05-22 22:13:20 +00:00
call DelayFrame
2015-02-07 10:43:08 +00:00
ld a, [wSerialExchangeNybbleReceiveData]
2014-05-22 22:13:20 +00:00
inc a
2015-07-15 06:16:06 +00:00
jr z, .syncLoop1
ld b, 10
.syncLoop2
2014-05-22 22:13:20 +00:00
call DelayFrame
2015-02-07 10:43:08 +00:00
call Serial_ExchangeNybble
2014-05-22 22:13:20 +00:00
dec b
2015-07-15 06:16:06 +00:00
jr nz, .syncLoop2
ld b, 10
.syncLoop3
2014-05-22 22:13:20 +00:00
call DelayFrame
2015-02-07 10:43:08 +00:00
call Serial_SendZeroByte
2014-05-22 22:13:20 +00:00
dec b
2015-07-15 06:16:06 +00:00
jr nz, .syncLoop3
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
ExecutePlayerMove:
2014-05-22 22:13:20 +00:00
xor a
2015-01-04 16:47:21 +00:00
ld [H_WHOSETURN], a ; set player's turn
2014-08-09 05:39:13 +00:00
ld a, [wPlayerSelectedMove]
2014-05-22 22:13:20 +00:00
inc a
2015-01-20 19:21:16 +00:00
jp z, ExecutePlayerMoveDone ; for selected move = FF, skip most of player's turn
2014-05-22 22:13:20 +00:00
xor a
2015-08-31 02:38:41 +00:00
ld [wMoveMissed], a
2015-03-31 18:40:22 +00:00
ld [wMonIsDisobedient], a
2015-03-31 18:28:42 +00:00
ld [wMoveDidntMiss], a
2014-05-22 22:13:20 +00:00
ld a, $a
2015-03-31 18:28:42 +00:00
ld [wDamageMultipliers], a
2015-07-15 06:16:06 +00:00
ld a, [wActionResultOrTookBattleTurn]
and a ; has the player already used the turn (e.g. by using an item, trying to run or switching pokemon)
2015-01-20 19:21:16 +00:00
jp nz, ExecutePlayerMoveDone
2014-05-22 22:13:20 +00:00
call PrintGhostText
2015-01-20 19:21:16 +00:00
jp z, ExecutePlayerMoveDone
2014-08-09 05:39:13 +00:00
call CheckPlayerStatusConditions
jr nz, .playerHasNoSpecialCondition
jp hl
.playerHasNoSpecialCondition
2014-05-22 22:13:20 +00:00
call GetCurrentMove
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2017-12-29 23:59:48 +00:00
bit CHARGING_UP, [hl] ; charging up for attack
2015-01-20 19:21:16 +00:00
jr nz, PlayerCanExecuteChargingMove
2014-08-09 05:39:13 +00:00
call CheckForDisobedience
2015-01-20 19:21:16 +00:00
jp z, ExecutePlayerMoveDone
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
CheckIfPlayerNeedsToChargeUp:
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveEffect]
2014-05-22 22:13:20 +00:00
cp CHARGE_EFFECT
2014-08-09 05:39:13 +00:00
jp z, JumpMoveEffect
2014-05-22 22:13:20 +00:00
cp FLY_EFFECT
2014-08-09 05:39:13 +00:00
jp z, JumpMoveEffect
2015-01-20 19:21:16 +00:00
jr PlayerCanExecuteMove
2014-05-22 22:13:20 +00:00
; in-battle stuff
2016-06-12 00:24:04 +00:00
PlayerCanExecuteChargingMove:
ld hl, wPlayerBattleStatus1
res CHARGING_UP, [hl] ; reset charging up and invulnerability statuses if mon was charging up for an attack
; being fully paralyzed or hurting oneself in confusion removes charging up status
; resulting in the Pokemon being invulnerable for the whole battle
res INVULNERABLE, [hl]
2016-06-12 00:24:04 +00:00
PlayerCanExecuteMove:
2014-05-22 22:13:20 +00:00
call PrintMonName1Text
ld hl, DecrementPP
ld de, wPlayerSelectedMove ; pointer to the move just used
ld b, BANK(DecrementPP)
2014-05-22 22:13:20 +00:00
call Bankswitch
ld a, [wPlayerMoveEffect] ; effect of the move just used
ld hl, ResidualEffects1
ld de, 1
2014-05-22 22:13:20 +00:00
call IsInArray
jp c, JumpMoveEffect ; ResidualEffects1 moves skip damage calculation and accuracy tests
2015-06-11 22:41:33 +00:00
; unless executed as part of their exclusive effect functions
ld a, [wPlayerMoveEffect]
ld hl, SpecialEffectsCont
ld de, 1
2014-05-22 22:13:20 +00:00
call IsInArray
call c, JumpMoveEffect ; execute the effects of SpecialEffectsCont moves (e.g. Wrap, Thrash) but don't skip anything
2016-06-12 00:24:04 +00:00
PlayerCalcMoveDamage:
ld a, [wPlayerMoveEffect]
ld hl, SetDamageEffects
ld de, 1
2015-01-23 03:05:13 +00:00
call IsInArray
jp c, .moveHitTest ; SetDamageEffects moves (e.g. Seismic Toss and Super Fang) skip damage calculation
2014-05-22 22:13:20 +00:00
call CriticalHitTest
call HandleCounterMove
jr z, handleIfPlayerMoveMissed
2014-08-09 05:39:13 +00:00
call GetDamageVarsForPlayerAttack
2014-05-22 22:13:20 +00:00
call CalculateDamage
jp z, playerCheckIfFlyOrChargeEffect ; for moves with 0 BP, skip any further damage calculation and, for now, skip MoveHitTest
; for these moves, accuracy tests will only occur if they are called as part of the effect itself
2014-05-22 22:13:20 +00:00
call AdjustDamageForMoveType
2014-08-09 05:39:13 +00:00
call RandomizeDamage
2015-01-20 19:21:16 +00:00
.moveHitTest
2014-05-22 22:13:20 +00:00
call MoveHitTest
2016-06-12 04:30:05 +00:00
handleIfPlayerMoveMissed:
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
jr z, getPlayerAnimationType
ld a, [wPlayerMoveEffect]
sub EXPLODE_EFFECT
jr z, playPlayerMoveAnimation ; don't play any animation if the move missed, unless it was EXPLODE_EFFECT
jr playerCheckIfFlyOrChargeEffect
2016-06-12 04:30:05 +00:00
getPlayerAnimationType:
ld a, [wPlayerMoveEffect]
2014-05-22 22:13:20 +00:00
and a
ld a, 4 ; move has no effect other than dealing damage
jr z, playPlayerMoveAnimation
ld a, 5 ; move has effect
2016-06-12 04:30:05 +00:00
playPlayerMoveAnimation:
2014-05-22 22:13:20 +00:00
push af
ld a, [wPlayerBattleStatus2]
bit HAS_SUBSTITUTE_UP, a
ld hl, HideSubstituteShowMonAnim
ld b, BANK(HideSubstituteShowMonAnim)
call nz, Bankswitch
2014-05-22 22:13:20 +00:00
pop af
ld [wAnimationType], a
ld a, [wPlayerMoveNum]
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
2015-01-20 19:21:16 +00:00
call HandleExplodingAnimation
2014-08-09 05:39:13 +00:00
call DrawPlayerHUDAndHPBar
ld a, [wPlayerBattleStatus2]
bit HAS_SUBSTITUTE_UP, a
ld hl, ReshowSubstituteAnim
ld b, BANK(ReshowSubstituteAnim)
call nz, Bankswitch
2015-01-20 19:21:16 +00:00
jr MirrorMoveCheck
2016-06-12 04:30:05 +00:00
playerCheckIfFlyOrChargeEffect:
ld c, 30
2014-05-22 22:13:20 +00:00
call DelayFrames
ld a, [wPlayerMoveEffect]
cp FLY_EFFECT
jr z, .playAnim
cp CHARGE_EFFECT
jr z, .playAnim
2015-01-20 19:21:16 +00:00
jr MirrorMoveCheck
.playAnim
2014-05-22 22:13:20 +00:00
xor a
ld [wAnimationType], a
ld a, STATUS_AFFECTED_ANIM
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
2016-06-12 04:30:05 +00:00
MirrorMoveCheck:
ld a, [wPlayerMoveEffect]
cp MIRROR_MOVE_EFFECT
jr nz, .metronomeCheck
2014-05-22 22:13:20 +00:00
call MirrorMoveCopyMove
jp z, ExecutePlayerMoveDone
2014-05-22 22:13:20 +00:00
xor a
ld [wMonIsDisobedient], a
jp CheckIfPlayerNeedsToChargeUp ; if Mirror Move was successful go back to damage calculation for copied move
2015-01-20 19:21:16 +00:00
.metronomeCheck
cp METRONOME_EFFECT
jr nz, .next
2014-05-22 22:13:20 +00:00
call MetronomePickMove
jp CheckIfPlayerNeedsToChargeUp ; Go back to damage calculation for the move picked by Metronome
2015-01-20 19:21:16 +00:00
.next
ld a, [wPlayerMoveEffect]
ld hl, ResidualEffects2
ld de, 1
2014-05-22 22:13:20 +00:00
call IsInArray
jp c, JumpMoveEffect ; done here after executing effects of ResidualEffects2
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
jr z, .moveDidNotMiss
2014-05-22 22:13:20 +00:00
call PrintMoveFailureText
ld a, [wPlayerMoveEffect]
cp EXPLODE_EFFECT ; even if Explosion or Selfdestruct missed, its effect still needs to be activated
jr z, .notDone
2015-01-23 03:05:13 +00:00
jp ExecutePlayerMoveDone ; otherwise, we're done if the move missed
2015-01-20 19:21:16 +00:00
.moveDidNotMiss
2014-05-22 22:13:20 +00:00
call ApplyAttackToEnemyPokemon
2014-08-09 05:39:13 +00:00
call PrintCriticalOHKOText
2014-05-22 22:13:20 +00:00
callab DisplayEffectiveness
ld a, 1
ld [wMoveDidntMiss], a
2015-01-20 19:21:16 +00:00
.notDone
ld a, [wPlayerMoveEffect]
ld hl, AlwaysHappenSideEffects
ld de, 1
2014-05-22 22:13:20 +00:00
call IsInArray
call c, JumpMoveEffect ; not done after executing effects of AlwaysHappenSideEffects
ld hl, wEnemyMonHP
ld a, [hli]
ld b, [hl]
2014-05-22 22:13:20 +00:00
or b
2015-01-04 16:47:21 +00:00
ret z ; don't do anything else if the enemy fainted
2014-05-22 22:13:20 +00:00
call HandleBuildingRage
ld hl, wPlayerBattleStatus1
bit ATTACKING_MULTIPLE_TIMES, [hl]
jr z, .executeOtherEffects
ld a, [wPlayerNumAttacksLeft]
2014-05-22 22:13:20 +00:00
dec a
ld [wPlayerNumAttacksLeft], a
jp nz, getPlayerAnimationType ; for multi-hit moves, apply attack until PlayerNumAttacksLeft hits 0 or the enemy faints.
; damage calculation and accuracy tests only happen for the first hit
res ATTACKING_MULTIPLE_TIMES, [hl] ; clear attacking multiple times status when all attacks are over
ld hl, MultiHitText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
ld [wPlayerNumHits], a
2015-01-20 19:21:16 +00:00
.executeOtherEffects
ld a, [wPlayerMoveEffect]
2014-05-22 22:13:20 +00:00
and a
jp z, ExecutePlayerMoveDone
ld hl, SpecialEffects
ld de, 1
2014-05-22 22:13:20 +00:00
call IsInArray
call nc, JumpMoveEffect ; move effects not included in SpecialEffects or in either of the ResidualEffect arrays,
; which are the effects not covered yet. Rage effect will be executed for a second time (though it's irrelevant).
; Includes side effects that only need to be called if the target didn't faint.
; Responsible for executing Twineedle's second side effect (poison).
2015-01-20 19:21:16 +00:00
jp ExecutePlayerMoveDone
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
MultiHitText:
2014-05-22 22:13:20 +00:00
TX_FAR _MultiHitText
db "@"
2016-06-12 00:24:04 +00:00
ExecutePlayerMoveDone:
2014-05-22 22:13:20 +00:00
xor a
ld [wActionResultOrTookBattleTurn], a
ld b, 1
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
PrintGhostText:
2014-05-22 22:13:20 +00:00
; print the ghost battle messages
call IsGhostBattle
ret nz
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr nz, .Ghost
ld a, [wBattleMonStatus] ; players turn
and SLP | (1 << FRZ)
2014-05-22 22:13:20 +00:00
ret nz
ld hl, ScaredText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
ret
.Ghost ; ghosts turn
ld hl, GetOutText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
ret
2016-06-12 00:24:04 +00:00
ScaredText:
2014-05-22 22:13:20 +00:00
TX_FAR _ScaredText
db "@"
2016-06-12 00:24:04 +00:00
GetOutText:
2014-05-22 22:13:20 +00:00
TX_FAR _GetOutText
db "@"
2016-06-12 00:24:04 +00:00
IsGhostBattle:
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
ret nz
ld a, [wCurMap]
cp POKEMON_TOWER_1F
jr c, .next
cp MR_FUJIS_HOUSE
jr nc, .next
ld b, SILPH_SCOPE
2014-08-09 05:39:13 +00:00
call IsItemInBag
2014-05-22 22:13:20 +00:00
ret z
.next
ld a, 1
2014-05-22 22:13:20 +00:00
and a
ret
2014-08-09 05:39:13 +00:00
; checks for various status conditions affecting the player mon
; stores whether the mon cannot use a move this turn in Z flag
2016-06-12 00:24:04 +00:00
CheckPlayerStatusConditions:
ld hl, wBattleMonStatus
ld a, [hl]
and SLP ; sleep mask
jr z, .FrozenCheck
2014-08-09 05:39:13 +00:00
; sleeping
2014-05-22 22:13:20 +00:00
dec a
ld [wBattleMonStatus], a ; decrement number of turns left
2014-05-22 22:13:20 +00:00
and a
jr z, .WakeUp ; if the number of turns hit 0, wake up
2014-08-09 05:39:13 +00:00
; fast asleep
2014-05-22 22:13:20 +00:00
xor a
ld [wAnimationType], a
ld a, SLP_ANIM - 1
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
ld hl, FastAsleepText
2014-05-22 22:13:20 +00:00
call PrintText
jr .sleepDone
.WakeUp
ld hl, WokeUpText
2014-05-22 22:13:20 +00:00
call PrintText
.sleepDone
xor a
ld [wPlayerUsedMove], a
ld hl, ExecutePlayerMoveDone ; player can't move this turn
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-05-22 22:13:20 +00:00
.FrozenCheck
bit FRZ, [hl] ; frozen?
jr z, .HeldInPlaceCheck
ld hl, IsFrozenText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
ld [wPlayerUsedMove], a
ld hl, ExecutePlayerMoveDone ; player can't move this turn
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-05-22 22:13:20 +00:00
.HeldInPlaceCheck
ld a, [wEnemyBattleStatus1]
bit USING_TRAPPING_MOVE, a ; is enemy using a mult-turn move like wrap?
jp z, .FlinchedCheck
ld hl, CantMoveText
2014-05-22 22:13:20 +00:00
call PrintText
ld hl, ExecutePlayerMoveDone ; player can't move this turn
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
.FlinchedCheck
ld hl, wPlayerBattleStatus1
bit FLINCHED, [hl]
jp z, .HyperBeamCheck
res FLINCHED, [hl] ; reset player's flinch status
ld hl, FlinchedText
2014-05-22 22:13:20 +00:00
call PrintText
ld hl, ExecutePlayerMoveDone ; player can't move this turn
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
.HyperBeamCheck
ld hl, wPlayerBattleStatus2
bit NEEDS_TO_RECHARGE, [hl]
jr z, .AnyMoveDisabledCheck
res NEEDS_TO_RECHARGE, [hl] ; reset player's recharge status
ld hl, MustRechargeText
2014-05-22 22:13:20 +00:00
call PrintText
ld hl, ExecutePlayerMoveDone ; player can't move this turn
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-08-09 05:39:13 +00:00
.AnyMoveDisabledCheck
ld hl, wPlayerDisabledMove
ld a, [hl]
2014-05-22 22:13:20 +00:00
and a
jr z, .ConfusedCheck
2014-05-22 22:13:20 +00:00
dec a
ld [hl], a
and $f ; did Disable counter hit 0?
jr nz, .ConfusedCheck
ld [hl], a
ld [wPlayerDisabledMoveNumber], a
ld hl, DisabledNoMoreText
2014-05-22 22:13:20 +00:00
call PrintText
2014-08-09 05:39:13 +00:00
.ConfusedCheck
ld a, [wPlayerBattleStatus1]
2015-01-04 16:47:21 +00:00
add a ; is player confused?
jr nc, .TriedToUseDisabledMoveCheck
ld hl, wPlayerConfusedCounter
2014-05-22 22:13:20 +00:00
dec [hl]
jr nz, .IsConfused
ld hl, wPlayerBattleStatus1
res CONFUSED, [hl] ; if confused counter hit 0, reset confusion status
ld hl, ConfusedNoMoreText
2014-05-22 22:13:20 +00:00
call PrintText
2014-08-09 05:39:13 +00:00
jr .TriedToUseDisabledMoveCheck
.IsConfused
ld hl, IsConfusedText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
ld [wAnimationType], a
ld a, CONF_ANIM - 1
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
call BattleRandom
cp $80 ; 50% chance to hurt itself
jr c, .TriedToUseDisabledMoveCheck
ld hl, wPlayerBattleStatus1
ld a, [hl]
and 1 << CONFUSED ; if mon hurts itself, clear every other status from wPlayerBattleStatus1
ld [hl], a
2015-01-04 16:47:21 +00:00
call HandleSelfConfusionDamage
2014-08-09 05:39:13 +00:00
jr .MonHurtItselfOrFullyParalysed
.TriedToUseDisabledMoveCheck
; prevents a disabled move that was selected before being disabled from being used
ld a, [wPlayerDisabledMoveNumber]
2014-05-22 22:13:20 +00:00
and a
jr z, .ParalysisCheck
ld hl, wPlayerSelectedMove
2014-05-22 22:13:20 +00:00
cp [hl]
jr nz, .ParalysisCheck
2014-05-22 22:13:20 +00:00
call PrintMoveIsDisabledText
ld hl, ExecutePlayerMoveDone ; if a disabled move was somehow selected, player can't move this turn
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-08-09 05:39:13 +00:00
2014-05-22 22:13:20 +00:00
.ParalysisCheck
ld hl, wBattleMonStatus
bit PAR, [hl]
jr z, .BideCheck
call BattleRandom
cp $3F ; 25% to be fully paralyzed
jr nc, .BideCheck
ld hl, FullyParalyzedText
2014-05-22 22:13:20 +00:00
call PrintText
2014-08-09 05:39:13 +00:00
.MonHurtItselfOrFullyParalysed
ld hl, wPlayerBattleStatus1
ld a, [hl]
2015-06-11 22:41:33 +00:00
; clear bide, thrashing, charging up, and trapping moves such as warp (already cleared for confusion damage)
2017-12-29 23:59:48 +00:00
and $ff ^ ((1 << STORING_ENERGY) | (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) | (1 << USING_TRAPPING_MOVE))
ld [hl], a
ld a, [wPlayerMoveEffect]
cp FLY_EFFECT
jr z, .FlyOrChargeEffect
cp CHARGE_EFFECT
jr z, .FlyOrChargeEffect
2014-08-09 05:39:13 +00:00
jr .NotFlyOrChargeEffect
.FlyOrChargeEffect
2014-05-22 22:13:20 +00:00
xor a
ld [wAnimationType], a
ld a, STATUS_AFFECTED_ANIM
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
2014-08-09 05:39:13 +00:00
.NotFlyOrChargeEffect
ld hl, ExecutePlayerMoveDone
2015-01-20 19:21:16 +00:00
jp .returnToHL ; if using a two-turn move, we need to recharge the first turn
2014-08-09 05:39:13 +00:00
.BideCheck
ld hl, wPlayerBattleStatus1
bit STORING_ENERGY, [hl] ; is mon using bide?
jr z, .ThrashingAboutCheck
xor a
ld [wPlayerMoveNum], a
ld hl, wDamage
ld a, [hli]
ld b, a
ld c, [hl]
ld hl, wPlayerBideAccumulatedDamage + 1
ld a, [hl]
2017-06-24 20:01:43 +00:00
add c ; accumulate damage taken
ld [hld], a
ld a, [hl]
2014-05-22 22:13:20 +00:00
adc b
ld [hl], a
ld hl, wPlayerNumAttacksLeft
2015-01-04 16:47:21 +00:00
dec [hl] ; did Bide counter hit 0?
jr z, .UnleashEnergy
ld hl, ExecutePlayerMoveDone
2015-01-20 19:21:16 +00:00
jp .returnToHL ; unless mon unleashes energy, can't move this turn
2014-08-09 05:39:13 +00:00
.UnleashEnergy
ld hl, wPlayerBattleStatus1
res STORING_ENERGY, [hl] ; not using bide any more
ld hl, UnleashedEnergyText
2014-05-22 22:13:20 +00:00
call PrintText
ld a, 1
ld [wPlayerMovePower], a
ld hl, wPlayerBideAccumulatedDamage + 1
ld a, [hld]
2014-05-22 22:13:20 +00:00
add a
ld b, a
ld [wDamage + 1], a
ld a, [hl]
2015-01-04 16:47:21 +00:00
rl a ; double the damage
ld [wDamage], a
2014-05-22 22:13:20 +00:00
or b
jr nz, .next
ld a, 1
ld [wMoveMissed], a
2014-08-09 05:39:13 +00:00
.next
2014-05-22 22:13:20 +00:00
xor a
ld [hli], a
ld [hl], a
ld a, BIDE
ld [wPlayerMoveNum], a
ld hl, handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-08-09 05:39:13 +00:00
.ThrashingAboutCheck
bit THRASHING_ABOUT, [hl] ; is mon using thrash or petal dance?
jr z, .MultiturnMoveCheck
ld a, THRASH
ld [wPlayerMoveNum], a
ld hl, ThrashingAboutText
2014-05-22 22:13:20 +00:00
call PrintText
ld hl, wPlayerNumAttacksLeft
dec [hl] ; did Thrashing About counter hit 0?
ld hl, PlayerCalcMoveDamage ; skip DecrementPP
jp nz, .returnToHL
2014-05-22 22:13:20 +00:00
push hl
ld hl, wPlayerBattleStatus1
res THRASHING_ABOUT, [hl] ; no longer thrashing about
set CONFUSED, [hl] ; confused
call BattleRandom
and 3
2014-05-22 22:13:20 +00:00
inc a
2015-01-04 16:47:21 +00:00
inc a ; confused for 2-5 turns
ld [wPlayerConfusedCounter], a
2015-01-04 16:47:21 +00:00
pop hl ; skip DecrementPP
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-08-09 05:39:13 +00:00
.MultiturnMoveCheck
bit USING_TRAPPING_MOVE, [hl] ; is mon using multi-turn move?
jp z, .RageCheck
ld hl, AttackContinuesText
2014-05-22 22:13:20 +00:00
call PrintText
ld a, [wPlayerNumAttacksLeft]
2015-01-04 16:47:21 +00:00
dec a ; did multi-turn move end?
ld [wPlayerNumAttacksLeft], a
ld hl, getPlayerAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit),
; DecrementPP and MoveHitTest
jp nz, .returnToHL
2015-01-20 19:21:16 +00:00
jp .returnToHL
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
.RageCheck
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus2]
2017-12-29 23:59:48 +00:00
bit USING_RAGE, a ; is mon using rage?
jp z, .checkPlayerStatusConditionsDone ; if we made it this far, mon can move normally this turn
2014-05-22 22:13:20 +00:00
ld a, RAGE
ld [wd11e], a
2014-05-22 22:13:20 +00:00
call GetMoveName
call CopyStringToCF4B
xor a
2015-08-31 02:38:41 +00:00
ld [wPlayerMoveEffect], a
2015-01-20 19:21:16 +00:00
ld hl, PlayerCanExecuteMove
jp .returnToHL
2014-05-22 22:13:20 +00:00
2015-01-20 19:21:16 +00:00
.returnToHL
2014-05-22 22:13:20 +00:00
xor a
ret
.checkPlayerStatusConditionsDone
2014-05-22 22:13:20 +00:00
ld a, $1
and a
ret
2016-06-12 00:24:04 +00:00
FastAsleepText:
2014-05-22 22:13:20 +00:00
TX_FAR _FastAsleepText
db "@"
2016-06-12 00:24:04 +00:00
WokeUpText:
2014-05-22 22:13:20 +00:00
TX_FAR _WokeUpText
db "@"
2016-06-12 00:24:04 +00:00
IsFrozenText:
2014-05-22 22:13:20 +00:00
TX_FAR _IsFrozenText
db "@"
2016-06-12 00:24:04 +00:00
FullyParalyzedText:
2014-05-22 22:13:20 +00:00
TX_FAR _FullyParalyzedText
db "@"
2016-06-12 00:24:04 +00:00
FlinchedText:
2014-05-22 22:13:20 +00:00
TX_FAR _FlinchedText
db "@"
2016-06-12 00:24:04 +00:00
MustRechargeText:
2014-05-22 22:13:20 +00:00
TX_FAR _MustRechargeText
db "@"
2016-06-12 00:24:04 +00:00
DisabledNoMoreText:
2014-05-22 22:13:20 +00:00
TX_FAR _DisabledNoMoreText
db "@"
2016-06-12 00:24:04 +00:00
IsConfusedText:
2014-05-22 22:13:20 +00:00
TX_FAR _IsConfusedText
db "@"
2016-06-12 00:24:04 +00:00
HurtItselfText:
2014-05-22 22:13:20 +00:00
TX_FAR _HurtItselfText
db "@"
2016-06-12 00:24:04 +00:00
ConfusedNoMoreText:
2014-05-22 22:13:20 +00:00
TX_FAR _ConfusedNoMoreText
db "@"
2016-06-12 00:24:04 +00:00
SavingEnergyText:
2014-05-22 22:13:20 +00:00
TX_FAR _SavingEnergyText
db "@"
2016-06-12 00:24:04 +00:00
UnleashedEnergyText:
2014-05-22 22:13:20 +00:00
TX_FAR _UnleashedEnergyText
db "@"
2016-06-12 00:24:04 +00:00
ThrashingAboutText:
2014-05-22 22:13:20 +00:00
TX_FAR _ThrashingAboutText
db "@"
2016-06-12 00:24:04 +00:00
AttackContinuesText:
2014-05-22 22:13:20 +00:00
TX_FAR _AttackContinuesText
db "@"
2016-06-12 00:24:04 +00:00
CantMoveText:
2014-05-22 22:13:20 +00:00
TX_FAR _CantMoveText
db "@"
2016-06-12 00:24:04 +00:00
PrintMoveIsDisabledText:
2014-08-09 05:39:13 +00:00
ld hl, wPlayerSelectedMove
2015-08-31 02:38:41 +00:00
ld de, wPlayerBattleStatus1
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .removeChargingUp
2014-05-22 22:13:20 +00:00
inc hl
2015-08-31 02:38:41 +00:00
ld de, wEnemyBattleStatus1
.removeChargingUp
2014-05-22 22:13:20 +00:00
ld a, [de]
2017-12-29 23:59:48 +00:00
res CHARGING_UP, a ; end the pokemon's
2014-05-22 22:13:20 +00:00
ld [de], a
ld a, [hl]
ld [wd11e], a
2014-05-22 22:13:20 +00:00
call GetMoveName
ld hl, MoveIsDisabledText
jp PrintText
2016-06-12 00:24:04 +00:00
MoveIsDisabledText:
2014-05-22 22:13:20 +00:00
TX_FAR _MoveIsDisabledText
db "@"
2016-06-12 00:24:04 +00:00
HandleSelfConfusionDamage:
2014-05-22 22:13:20 +00:00
ld hl, HurtItselfText
call PrintText
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonDefense
2014-05-22 22:13:20 +00:00
ld a, [hli]
push af
ld a, [hld]
push af
ld a, [wBattleMonDefense]
2014-05-22 22:13:20 +00:00
ld [hli], a
ld a, [wBattleMonDefense + 1]
2014-05-22 22:13:20 +00:00
ld [hl], a
2015-08-31 02:38:41 +00:00
ld hl, wPlayerMoveEffect
2014-05-22 22:13:20 +00:00
push hl
ld a, [hl]
push af
xor a
ld [hli], a
2015-01-04 16:47:21 +00:00
ld [wCriticalHitOrOHKO], a ; self-inflicted confusion damage can't be a Critical Hit
ld a, 40 ; 40 base power
2014-05-22 22:13:20 +00:00
ld [hli], a
xor a
ld [hl], a
2014-08-09 05:39:13 +00:00
call GetDamageVarsForPlayerAttack
call CalculateDamage ; ignores AdjustDamageForMoveType (type-less damage), RandomizeDamage,
; and MoveHitTest (always hits)
2014-05-22 22:13:20 +00:00
pop af
pop hl
ld [hl], a
ld hl, wEnemyMonDefense + 1
2014-05-22 22:13:20 +00:00
pop af
ld [hld], a
pop af
ld [hl], a
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
2014-08-09 05:39:13 +00:00
call DrawPlayerHUDAndHPBar
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
jp ApplyDamageToPlayerPokemon
2016-06-12 00:24:04 +00:00
PrintMonName1Text:
2014-05-22 22:13:20 +00:00
ld hl, MonName1Text
jp PrintText
2015-06-12 18:37:20 +00:00
; this function wastes time calling DetermineExclamationPointTextNum
; and choosing between Used1Text and Used2Text, even though
; those text strings are identical and both continue at PrintInsteadText
2015-06-12 18:45:52 +00:00
; this likely had to do with Japanese grammar that got translated,
; but the functionality didn't get removed
2016-06-12 00:24:04 +00:00
MonName1Text:
2014-05-22 22:13:20 +00:00
TX_FAR _MonName1Text
2015-07-03 19:58:50 +00:00
TX_ASM
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveNum]
ld hl, wPlayerUsedMove
2016-06-12 04:30:05 +00:00
jr z, .playerTurn
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
ld hl, wEnemyUsedMove
2016-06-12 04:30:05 +00:00
.playerTurn
2014-05-22 22:13:20 +00:00
ld [hl], a
ld [wd11e], a
2015-06-12 18:37:20 +00:00
call DetermineExclamationPointTextNum
2015-03-31 18:40:22 +00:00
ld a, [wMonIsDisobedient]
2014-05-22 22:13:20 +00:00
and a
ld hl, Used2Text
ret nz
ld a, [wd11e]
cp 3
2014-05-22 22:13:20 +00:00
ld hl, Used2Text
ret c
ld hl, Used1Text
ret
2016-06-12 00:24:04 +00:00
Used1Text:
2014-05-22 22:13:20 +00:00
TX_FAR _Used1Text
2015-07-03 19:58:50 +00:00
TX_ASM
2014-05-22 22:13:20 +00:00
jr PrintInsteadText
2016-06-12 00:24:04 +00:00
Used2Text:
2014-05-22 22:13:20 +00:00
TX_FAR _Used2Text
2015-07-03 19:58:50 +00:00
TX_ASM
2015-06-12 18:37:20 +00:00
; fall through
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
PrintInsteadText:
2015-03-31 18:40:22 +00:00
ld a, [wMonIsDisobedient]
2014-05-22 22:13:20 +00:00
and a
2015-06-12 18:37:20 +00:00
jr z, PrintMoveName
2014-05-22 22:13:20 +00:00
ld hl, InsteadText
ret
2016-06-12 00:24:04 +00:00
InsteadText:
2014-05-22 22:13:20 +00:00
TX_FAR _InsteadText
2015-07-03 19:58:50 +00:00
TX_ASM
2015-06-12 18:37:20 +00:00
; fall through
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
PrintMoveName:
2015-06-12 18:37:20 +00:00
ld hl, _PrintMoveName
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
_PrintMoveName:
2014-05-22 22:13:20 +00:00
TX_FAR _CF4BText
2015-07-03 19:58:50 +00:00
TX_ASM
2014-05-22 22:13:20 +00:00
ld hl, ExclamationPointPointerTable
2015-06-12 18:37:20 +00:00
ld a, [wd11e] ; exclamation point num
2014-05-22 22:13:20 +00:00
add a
push bc
ld b, $0
ld c, a
add hl, bc
pop bc
ld a, [hli]
ld h, [hl]
ld l, a
ret
2016-06-12 00:24:04 +00:00
ExclamationPointPointerTable:
2014-05-22 22:13:20 +00:00
dw ExclamationPoint1Text
dw ExclamationPoint2Text
dw ExclamationPoint3Text
dw ExclamationPoint4Text
dw ExclamationPoint5Text
2016-06-12 00:24:04 +00:00
ExclamationPoint1Text:
2014-05-22 22:13:20 +00:00
TX_FAR _ExclamationPoint1Text
db "@"
2016-06-12 00:24:04 +00:00
ExclamationPoint2Text:
2014-05-22 22:13:20 +00:00
TX_FAR _ExclamationPoint2Text
db "@"
2016-06-12 00:24:04 +00:00
ExclamationPoint3Text:
2014-05-22 22:13:20 +00:00
TX_FAR _ExclamationPoint3Text
db "@"
2016-06-12 00:24:04 +00:00
ExclamationPoint4Text:
2014-05-22 22:13:20 +00:00
TX_FAR _ExclamationPoint4Text
db "@"
2016-06-12 00:24:04 +00:00
ExclamationPoint5Text:
2014-05-22 22:13:20 +00:00
TX_FAR _ExclamationPoint5Text
db "@"
2015-06-12 18:37:20 +00:00
; this function does nothing useful
; if the move being used is in set [1-4] from ExclamationPointMoveSets,
; use ExclamationPoint[1-4]Text
; otherwise, use ExclamationPoint5Text
; but all five text strings are identical
2015-06-12 18:45:52 +00:00
; this likely had to do with Japanese grammar that got translated,
; but the functionality didn't get removed
2016-06-12 00:24:04 +00:00
DetermineExclamationPointTextNum:
2014-05-22 22:13:20 +00:00
push bc
2015-06-12 18:37:20 +00:00
ld a, [wd11e] ; move ID
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
2015-06-12 18:37:20 +00:00
ld hl, ExclamationPointMoveSets
.loop
2014-05-22 22:13:20 +00:00
ld a, [hli]
cp $ff
2015-06-12 18:37:20 +00:00
jr z, .done
2014-05-22 22:13:20 +00:00
cp c
2015-06-12 18:37:20 +00:00
jr z, .done
2014-05-22 22:13:20 +00:00
and a
2015-06-12 18:37:20 +00:00
jr nz, .loop
2014-05-22 22:13:20 +00:00
inc b
2015-06-12 18:37:20 +00:00
jr .loop
.done
2014-05-22 22:13:20 +00:00
ld a, b
2015-06-12 18:37:20 +00:00
ld [wd11e], a ; exclamation point num
2014-05-22 22:13:20 +00:00
pop bc
ret
2016-06-12 00:24:04 +00:00
ExclamationPointMoveSets:
2014-05-22 22:13:20 +00:00
db SWORDS_DANCE, GROWTH
db $00
db RECOVER, BIDE, SELFDESTRUCT, AMNESIA
db $00
db MEDITATE, AGILITY, TELEPORT, MIMIC, DOUBLE_TEAM, BARRAGE
db $00
db POUND, SCRATCH, VICEGRIP, WING_ATTACK, FLY, BIND, SLAM, HORN_ATTACK, BODY_SLAM
db WRAP, THRASH, TAIL_WHIP, LEER, BITE, GROWL, ROAR, SING, PECK, COUNTER
db STRENGTH, ABSORB, STRING_SHOT, EARTHQUAKE, FISSURE, DIG, TOXIC, SCREECH, HARDEN
db MINIMIZE, WITHDRAW, DEFENSE_CURL, METRONOME, LICK, CLAMP, CONSTRICT, POISON_GAS
db LEECH_LIFE, BUBBLE, FLASH, SPLASH, ACID_ARMOR, FURY_SWIPES, REST, SHARPEN, SLASH, SUBSTITUTE
db $00
db $FF ; terminator
2016-06-12 00:24:04 +00:00
PrintMoveFailureText:
2015-08-31 02:38:41 +00:00
ld de, wPlayerMoveEffect
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .playersTurn
2015-08-31 02:38:41 +00:00
ld de, wEnemyMoveEffect
2014-08-09 05:39:13 +00:00
.playersTurn
ld hl, DoesntAffectMonText
2015-03-31 18:28:42 +00:00
ld a, [wDamageMultipliers]
2014-05-22 22:13:20 +00:00
and $7f
jr z, .gotTextToPrint
2014-08-09 05:39:13 +00:00
ld hl, AttackMissedText
ld a, [wCriticalHitOrOHKO]
2014-05-22 22:13:20 +00:00
cp $ff
jr nz, .gotTextToPrint
2014-08-09 05:39:13 +00:00
ld hl, UnaffectedText
.gotTextToPrint
2014-05-22 22:13:20 +00:00
push de
call PrintText
xor a
2014-08-09 05:39:13 +00:00
ld [wCriticalHitOrOHKO], a
2014-05-22 22:13:20 +00:00
pop de
ld a, [de]
cp JUMP_KICK_EFFECT
ret nz
2015-01-04 16:47:21 +00:00
; if you get here, the mon used jump kick or hi jump kick and missed
2015-08-31 02:38:41 +00:00
ld hl, wDamage ; since the move missed, wDamage will always contain 0 at this point.
2015-06-11 22:41:33 +00:00
; Thus, recoil damage will always be equal to 1
; even if it was intended to be potential damage/8.
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, [hl]
srl a
rr b
srl a
rr b
srl a
rr b
ld [hl], b
dec hl
ld [hli], a
or b
2015-01-20 19:21:16 +00:00
jr nz, .applyRecoil
2014-05-22 22:13:20 +00:00
inc a
ld [hl], a
2015-01-20 19:21:16 +00:00
.applyRecoil
2014-08-09 05:39:13 +00:00
ld hl, KeptGoingAndCrashedText
2014-05-22 22:13:20 +00:00
call PrintText
ld b, $4
2015-07-12 23:24:03 +00:00
predef PredefShakeScreenHorizontally
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr nz, .enemyTurn
2014-05-22 22:13:20 +00:00
jp ApplyDamageToPlayerPokemon
2015-01-20 19:21:16 +00:00
.enemyTurn
2014-05-22 22:13:20 +00:00
jp ApplyDamageToEnemyPokemon
2016-06-12 00:24:04 +00:00
AttackMissedText:
2014-05-22 22:13:20 +00:00
TX_FAR _AttackMissedText
db "@"
2016-06-12 00:24:04 +00:00
KeptGoingAndCrashedText:
2014-05-22 22:13:20 +00:00
TX_FAR _KeptGoingAndCrashedText
db "@"
2016-06-12 00:24:04 +00:00
UnaffectedText:
2014-05-22 22:13:20 +00:00
TX_FAR _UnaffectedText
db "@"
2016-06-12 00:24:04 +00:00
PrintDoesntAffectText:
2014-08-09 05:39:13 +00:00
ld hl, DoesntAffectMonText
2014-05-22 22:13:20 +00:00
jp PrintText
2016-06-12 00:24:04 +00:00
DoesntAffectMonText:
2014-05-22 22:13:20 +00:00
TX_FAR _DoesntAffectMonText
db "@"
2014-08-09 05:39:13 +00:00
; if there was a critical hit or an OHKO was successful, print the corresponding text
2016-06-12 00:24:04 +00:00
PrintCriticalOHKOText:
2014-08-09 05:39:13 +00:00
ld a, [wCriticalHitOrOHKO]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .done ; do nothing if there was no critical hit or successful OHKO
2014-05-22 22:13:20 +00:00
dec a
add a
2014-08-09 05:39:13 +00:00
ld hl, CriticalOHKOTextPointers
2014-05-22 22:13:20 +00:00
ld b, $0
ld c, a
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
call PrintText
xor a
2014-08-09 05:39:13 +00:00
ld [wCriticalHitOrOHKO], a
.done
ld c, 20
2014-05-22 22:13:20 +00:00
jp DelayFrames
2016-06-12 00:24:04 +00:00
CriticalOHKOTextPointers:
2014-05-22 22:13:20 +00:00
dw CriticalHitText
dw OHKOText
2016-06-12 00:24:04 +00:00
CriticalHitText:
2014-05-22 22:13:20 +00:00
TX_FAR _CriticalHitText
db "@"
2016-06-12 00:24:04 +00:00
OHKOText:
2014-05-22 22:13:20 +00:00
TX_FAR _OHKOText
db "@"
2014-08-09 05:39:13 +00:00
; checks if a traded mon will disobey due to lack of badges
; stores whether the mon will use a move in Z flag
2016-06-12 00:24:04 +00:00
CheckForDisobedience:
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 18:40:22 +00:00
ld [wMonIsDisobedient], a
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-08-09 05:39:13 +00:00
jr nz, .checkIfMonIsTraded
2014-05-22 22:13:20 +00:00
ld a, $1
and a
ret
2014-08-09 05:39:13 +00:00
; compare the mon's original trainer ID with the player's ID to see if it was traded
.checkIfMonIsTraded
ld hl, wPartyMon1OTID
ld bc, wPartyMon2 - wPartyMon1
ld a, [wPlayerMonNumber]
2014-05-22 22:13:20 +00:00
call AddNTimes
2014-08-09 05:39:13 +00:00
ld a, [wPlayerID]
2014-05-22 22:13:20 +00:00
cp [hl]
2014-08-09 05:39:13 +00:00
jr nz, .monIsTraded
2014-05-22 22:13:20 +00:00
inc hl
2014-08-09 05:39:13 +00:00
ld a, [wPlayerID + 1]
2014-05-22 22:13:20 +00:00
cp [hl]
2014-08-09 05:39:13 +00:00
jp z, .canUseMove
; it was traded
.monIsTraded
2014-05-22 22:13:20 +00:00
; what level might disobey?
2015-08-31 02:38:41 +00:00
ld hl, wObtainedBadges
2014-05-22 22:13:20 +00:00
bit 7, [hl]
ld a, 101
2014-08-09 05:39:13 +00:00
jr nz, .next
2014-05-22 22:13:20 +00:00
bit 5, [hl]
ld a, 70
2014-08-09 05:39:13 +00:00
jr nz, .next
2014-05-22 22:13:20 +00:00
bit 3, [hl]
ld a, 50
2014-08-09 05:39:13 +00:00
jr nz, .next
2014-05-22 22:13:20 +00:00
bit 1, [hl]
ld a, 30
2014-08-09 05:39:13 +00:00
jr nz, .next
2014-05-22 22:13:20 +00:00
ld a, 10
2014-08-09 05:39:13 +00:00
.next
2014-05-22 22:13:20 +00:00
ld b, a
ld c, a
2014-08-09 05:39:13 +00:00
ld a, [wBattleMonLevel]
2014-05-22 22:13:20 +00:00
ld d, a
add b
ld b, a
2014-08-09 05:39:13 +00:00
jr nc, .noCarry
ld b, $ff ; cap b at $ff
.noCarry
2014-05-22 22:13:20 +00:00
ld a, c
cp d
2014-08-09 05:39:13 +00:00
jp nc, .canUseMove
.loop1
call BattleRandom
2014-05-22 22:13:20 +00:00
swap a
cp b
2014-08-09 05:39:13 +00:00
jr nc, .loop1
2014-05-22 22:13:20 +00:00
cp c
2014-08-09 05:39:13 +00:00
jp c, .canUseMove
.loop2
call BattleRandom
2014-05-22 22:13:20 +00:00
cp b
2014-08-09 05:39:13 +00:00
jr nc, .loop2
2014-05-22 22:13:20 +00:00
cp c
2014-08-09 05:39:13 +00:00
jr c, .useRandomMove
2014-05-22 22:13:20 +00:00
ld a, d
sub c
ld b, a
call BattleRandom
2014-05-22 22:13:20 +00:00
swap a
sub b
2014-08-09 05:39:13 +00:00
jr c, .monNaps
2014-05-22 22:13:20 +00:00
cp b
2014-08-09 05:39:13 +00:00
jr nc, .monDoesNothing
2014-05-22 22:13:20 +00:00
ld hl, WontObeyText
call PrintText
2015-01-04 16:47:21 +00:00
call HandleSelfConfusionDamage
2014-08-09 05:39:13 +00:00
jp .cannotUseMove
.monNaps
call BattleRandom
2014-05-22 22:13:20 +00:00
add a
swap a
2014-08-09 05:39:13 +00:00
and SLP ; sleep mask
jr z, .monNaps ; keep trying until we get at least 1 turn of sleep
ld [wBattleMonStatus], a
2014-05-22 22:13:20 +00:00
ld hl, BeganToNapText
2014-08-09 05:39:13 +00:00
jr .printText
.monDoesNothing
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
ld hl, LoafingAroundText
and a
2014-08-09 05:39:13 +00:00
jr z, .printText
2014-05-22 22:13:20 +00:00
ld hl, WontObeyText
dec a
2014-08-09 05:39:13 +00:00
jr z, .printText
2014-05-22 22:13:20 +00:00
ld hl, TurnedAwayText
dec a
2014-08-09 05:39:13 +00:00
jr z, .printText
2014-05-22 22:13:20 +00:00
ld hl, IgnoredOrdersText
2014-08-09 05:39:13 +00:00
.printText
2014-05-22 22:13:20 +00:00
call PrintText
2014-08-09 05:39:13 +00:00
jr .cannotUseMove
.useRandomMove
ld a, [wBattleMonMoves + 1]
2014-08-09 05:39:13 +00:00
and a ; is the second move slot empty?
jr z, .monDoesNothing ; mon will not use move if it only knows one move
ld a, [wPlayerDisabledMoveNumber]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr nz, .monDoesNothing
ld a, [wPlayerSelectedMove]
cp STRUGGLE
jr z, .monDoesNothing ; mon will not use move if struggling
; check if only one move has remaining PP
ld hl, wBattleMonPP
2014-05-22 22:13:20 +00:00
push hl
ld a, [hli]
and $3f
ld b, a
ld a, [hli]
and $3f
add b
ld b, a
ld a, [hli]
and $3f
add b
ld b, a
ld a, [hl]
and $3f
add b
pop hl
push af
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
add hl, bc
ld a, [hl]
and $3f
ld b, a
pop af
cp b
2014-08-09 05:39:13 +00:00
jr z, .monDoesNothing ; mon will not use move if only one move has remaining PP
2014-05-22 22:13:20 +00:00
ld a, $1
2015-03-31 18:40:22 +00:00
ld [wMonIsDisobedient], a
2014-08-09 05:39:13 +00:00
ld a, [wMaxMenuItem]
2014-05-22 22:13:20 +00:00
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
ld c, a
2014-08-09 05:39:13 +00:00
.chooseMove
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
cp b
2014-08-09 05:39:13 +00:00
jr nc, .chooseMove ; if the random number is greater than the move count, choose another
2014-05-22 22:13:20 +00:00
cp c
2014-08-09 05:39:13 +00:00
jr z, .chooseMove ; if the random number matches the move the player selected, choose another
ld [wCurrentMenuItem], a
ld hl, wBattleMonPP
2014-05-22 22:13:20 +00:00
ld e, a
ld d, $0
add hl, de
ld a, [hl]
2014-08-09 05:39:13 +00:00
and a ; does the move have any PP left?
jr z, .chooseMove ; if the move has no PP left, choose another
ld a, [wCurrentMenuItem]
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
ld hl, wBattleMonMoves
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [wPlayerSelectedMove], a
2014-05-22 22:13:20 +00:00
call GetCurrentMove
2014-08-09 05:39:13 +00:00
.canUseMove
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
and a; clear Z flag
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
.cannotUseMove
xor a ; set Z flag
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
LoafingAroundText:
2014-05-22 22:13:20 +00:00
TX_FAR _LoafingAroundText
db "@"
2016-06-12 00:24:04 +00:00
BeganToNapText:
2014-05-22 22:13:20 +00:00
TX_FAR _BeganToNapText
db "@"
2016-06-12 00:24:04 +00:00
WontObeyText:
2014-05-22 22:13:20 +00:00
TX_FAR _WontObeyText
db "@"
2016-06-12 00:24:04 +00:00
TurnedAwayText:
2014-05-22 22:13:20 +00:00
TX_FAR _TurnedAwayText
db "@"
2016-06-12 00:24:04 +00:00
IgnoredOrdersText:
2014-05-22 22:13:20 +00:00
TX_FAR _IgnoredOrdersText
db "@"
2014-08-09 05:39:13 +00:00
; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the player mon
2016-06-12 00:24:04 +00:00
GetDamageVarsForPlayerAttack:
2014-05-22 22:13:20 +00:00
xor a
2015-08-31 02:38:41 +00:00
ld hl, wDamage ; damage to eventually inflict, initialise to zero
2014-05-22 22:13:20 +00:00
ldi [hl], a
ld [hl], a
2015-08-31 02:38:41 +00:00
ld hl, wPlayerMovePower
2014-08-09 05:39:13 +00:00
ld a, [hli]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
ld d, a ; d = move power
ret z ; return if move power is zero
2015-08-31 02:38:41 +00:00
ld a, [hl] ; a = [wPlayerMoveType]
2014-08-09 05:39:13 +00:00
cp FIRE ; types >= FIRE are all special
2014-05-22 22:13:20 +00:00
jr nc, .specialAttack
.physicalAttack
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonDefense
ld a, [hli]
2014-05-22 22:13:20 +00:00
ld b, a
2014-08-09 05:39:13 +00:00
ld c, [hl] ; bc = enemy defense
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus3]
2017-12-29 23:59:48 +00:00
bit HAS_REFLECT_UP, a ; check for Reflect
2014-08-09 05:39:13 +00:00
jr z, .physicalAttackCritCheck
; if the enemy has used Reflect, double the enemy's defense
sla c
2015-01-23 03:05:13 +00:00
rl b
2014-08-09 05:39:13 +00:00
.physicalAttackCritCheck
ld hl, wBattleMonAttack
ld a, [wCriticalHitOrOHKO]
and a ; check for critical hit
jr z, .scaleStats
; in the case of a critical hit, reset the player's attack and the enemy's defense to their base values
ld c, 3 ; defense stat
call GetEnemyMonStat
ld a, [H_PRODUCT + 2]
2014-05-22 22:13:20 +00:00
ld b, a
ld a, [H_PRODUCT + 3]
2014-05-22 22:13:20 +00:00
ld c, a
push bc
ld hl, wPartyMon1Attack
2014-05-22 22:13:20 +00:00
ld a, [wPlayerMonNumber]
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
pop bc
2014-08-09 05:39:13 +00:00
jr .scaleStats
2014-05-22 22:13:20 +00:00
.specialAttack
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonSpecial
ld a, [hli]
2014-05-22 22:13:20 +00:00
ld b, a
2014-08-09 05:39:13 +00:00
ld c, [hl] ; bc = enemy special
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus3]
2017-12-29 23:59:48 +00:00
bit HAS_LIGHT_SCREEN_UP, a ; check for Light Screen
2014-08-09 05:39:13 +00:00
jr z, .specialAttackCritCheck
; if the enemy has used Light Screen, double the enemy's special
sla c
2014-05-22 22:13:20 +00:00
rl b
2015-01-04 16:47:21 +00:00
; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if
2017-06-24 20:01:43 +00:00
; a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen
2014-08-09 05:39:13 +00:00
.specialAttackCritCheck
ld hl, wBattleMonSpecial
2014-08-09 05:39:13 +00:00
ld a, [wCriticalHitOrOHKO]
and a ; check for critical hit
jr z, .scaleStats
; in the case of a critical hit, reset the player's and enemy's specials to their base values
ld c, 5 ; special stat
call GetEnemyMonStat
ld a, [H_PRODUCT + 2]
2014-05-22 22:13:20 +00:00
ld b, a
ld a, [H_PRODUCT + 3]
2014-05-22 22:13:20 +00:00
ld c, a
push bc
ld hl, wPartyMon1Special
2014-05-22 22:13:20 +00:00
ld a, [wPlayerMonNumber]
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
pop bc
2014-08-09 05:39:13 +00:00
; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4
; this allows values with up to 10 bits (values up to 1023) to be handled
; anything larger will wrap around
.scaleStats
ld a, [hli]
2014-05-22 22:13:20 +00:00
ld l, [hl]
2014-08-09 05:39:13 +00:00
ld h, a ; hl = player's offensive stat
or b ; is either high byte nonzero?
jr z, .next ; if not, we don't need to scale
2015-01-04 16:47:21 +00:00
; bc /= 4 (scale enemy's defensive stat)
2014-08-09 05:39:13 +00:00
srl b
2014-05-22 22:13:20 +00:00
rr c
srl b
rr c
2015-01-23 03:05:13 +00:00
; defensive stat can actually end up as 0, leading to a division by 0 freeze during damage calculation
2015-01-04 16:47:21 +00:00
; hl /= 4 (scale player's offensive stat)
2014-08-09 05:39:13 +00:00
srl h
2014-05-22 22:13:20 +00:00
rr l
srl h
rr l
ld a, l
2014-08-09 05:39:13 +00:00
or h ; is the player's offensive stat 0?
jr nz, .next
inc l ; if the player's offensive stat is 0, bump it up to 1
.next
ld b, l ; b = player's offensive stat (possibly scaled)
; (c already contains enemy's defensive stat (possibly scaled))
2014-08-09 05:39:13 +00:00
ld a, [wBattleMonLevel]
ld e, a ; e = level
ld a, [wCriticalHitOrOHKO]
and a ; check for critical hit
jr z, .done
sla e ; double level if it was a critical hit
.done
ld a, 1
2014-05-22 22:13:20 +00:00
and a
ret
2014-08-09 05:39:13 +00:00
; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the enemy mon
2016-06-12 00:24:04 +00:00
GetDamageVarsForEnemyAttack:
2015-08-31 02:38:41 +00:00
ld hl, wDamage ; damage to eventually inflict, initialise to zero
2014-05-22 22:13:20 +00:00
xor a
ld [hli], a
ld [hl], a
2015-08-31 02:38:41 +00:00
ld hl, wEnemyMovePower
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
ld d, a ; d = move power
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
ret z ; return if move power is zero
2015-08-31 02:38:41 +00:00
ld a, [hl] ; a = [wEnemyMoveType]
2014-08-09 05:39:13 +00:00
cp FIRE ; types >= FIRE are all special
jr nc, .specialAttack
.physicalAttack
ld hl, wBattleMonDefense
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, a
2014-08-09 05:39:13 +00:00
ld c, [hl] ; bc = player defense
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus3]
2017-12-29 23:59:48 +00:00
bit HAS_REFLECT_UP, a ; check for Reflect
2014-08-09 05:39:13 +00:00
jr z, .physicalAttackCritCheck
; if the player has used Reflect, double the player's defense
2014-05-22 22:13:20 +00:00
sla c
rl b
2014-08-09 05:39:13 +00:00
.physicalAttackCritCheck
ld hl, wEnemyMonAttack
2014-08-09 05:39:13 +00:00
ld a, [wCriticalHitOrOHKO]
and a ; check for critical hit
jr z, .scaleStats
; in the case of a critical hit, reset the player's defense and the enemy's attack to their base values
ld hl, wPartyMon1Defense
2014-08-09 05:39:13 +00:00
ld a, [wPlayerMonNumber]
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, [hli]
ld b, a
ld c, [hl]
push bc
2014-08-09 05:39:13 +00:00
ld c, 2 ; attack stat
call GetEnemyMonStat
ld hl, H_PRODUCT + 2
2014-05-22 22:13:20 +00:00
pop bc
2014-08-09 05:39:13 +00:00
jr .scaleStats
.specialAttack
ld hl, wBattleMonSpecial
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, a
ld c, [hl]
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus3]
2017-12-29 23:59:48 +00:00
bit HAS_LIGHT_SCREEN_UP, a ; check for Light Screen
2014-08-09 05:39:13 +00:00
jr z, .specialAttackCritCheck
; if the player has used Light Screen, double the player's special
2014-05-22 22:13:20 +00:00
sla c
rl b
2015-01-04 16:47:21 +00:00
; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if
2017-06-24 20:01:43 +00:00
; a Pokemon with 512 or more Defense has used Reflect, or if a Pokemon with 512 or more Special has used Light Screen
2014-08-09 05:39:13 +00:00
.specialAttackCritCheck
ld hl, wEnemyMonSpecial
ld a, [wCriticalHitOrOHKO]
and a ; check for critical hit
jr z, .scaleStats
; in the case of a critical hit, reset the player's and enemy's specials to their base values
ld hl, wPartyMon1Special
ld a, [wPlayerMonNumber]
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, [hli]
ld b, a
ld c, [hl]
push bc
2014-08-09 05:39:13 +00:00
ld c, 5 ; special stat
call GetEnemyMonStat
ld hl, H_PRODUCT + 2
2014-05-22 22:13:20 +00:00
pop bc
2014-08-09 05:39:13 +00:00
; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4
; this allows values with up to 10 bits (values up to 1023) to be handled
; anything larger will wrap around
.scaleStats
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld l, [hl]
2014-08-09 05:39:13 +00:00
ld h, a ; hl = enemy's offensive stat
or b ; is either high byte nonzero?
jr z, .next ; if not, we don't need to scale
; bc /= 4 (scale player's defensive stat)
2014-05-22 22:13:20 +00:00
srl b
rr c
srl b
rr c
2015-01-23 03:05:13 +00:00
; defensive stat can actually end up as 0, leading to a division by 0 freeze during damage calculation
2014-08-09 05:39:13 +00:00
; hl /= 4 (scale enemy's offensive stat)
2014-05-22 22:13:20 +00:00
srl h
rr l
srl h
rr l
ld a, l
2014-08-09 05:39:13 +00:00
or h ; is the enemy's offensive stat 0?
jr nz, .next
inc l ; if the enemy's offensive stat is 0, bump it up to 1
.next
ld b, l ; b = enemy's offensive stat (possibly scaled)
; (c already contains player's defensive stat (possibly scaled))
2014-08-09 05:39:13 +00:00
ld a, [wEnemyMonLevel]
2014-05-22 22:13:20 +00:00
ld e, a
2014-08-09 05:39:13 +00:00
ld a, [wCriticalHitOrOHKO]
and a ; check for critical hit
jr z, .done
sla e ; double level if it was a critical hit
.done
2014-05-22 22:13:20 +00:00
ld a, $1
and a
and a
ret
2014-08-09 05:39:13 +00:00
; get stat c of enemy mon
; c: stat to get (HP=1,Attack=2,Defense=3,Speed=4,Special=5)
2016-06-12 00:24:04 +00:00
GetEnemyMonStat:
2014-05-22 22:13:20 +00:00
push de
push bc
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2015-01-20 19:21:16 +00:00
jr nz, .notLinkBattle
ld hl, wEnemyMon1Stats
2014-05-22 22:13:20 +00:00
dec c
sla c
ld b, $0
add hl, bc
ld a, [wEnemyMonPartyPos]
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, [hli]
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
ld a, [hl]
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
pop bc
pop de
ret
2015-01-20 19:21:16 +00:00
.notLinkBattle
2014-08-09 05:39:13 +00:00
ld a, [wEnemyMonLevel]
2015-08-31 02:38:41 +00:00
ld [wCurEnemyLVL], a
ld a, [wEnemyMonSpecies]
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
ld hl, wEnemyMonDVs
2015-02-08 02:37:40 +00:00
ld de, wLoadedMonSpeedExp
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
pop bc
ld b, $0
2015-02-08 02:37:40 +00:00
ld hl, wLoadedMonSpeedExp - $b ; this base address makes CalcStat look in [wLoadedMonSpeedExp] for DVs
2014-05-22 22:13:20 +00:00
call CalcStat
pop de
ret
2016-06-12 00:24:04 +00:00
CalculateDamage:
2014-05-22 22:13:20 +00:00
; input:
2016-07-28 03:33:48 +00:00
; b: attack
; c: opponent defense
; d: base power
; e: level
2014-05-22 22:13:20 +00:00
2015-03-31 18:50:49 +00:00
ld a, [H_WHOSETURN] ; whose turn?
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveEffect]
2014-05-22 22:13:20 +00:00
jr z, .effect
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
.effect
; EXPLODE_EFFECT halves defense.
cp EXPLODE_EFFECT
2014-05-22 22:13:20 +00:00
jr nz, .ok
srl c
jr nz, .ok
inc c ; ...with a minimum value of 1 (used as a divisor later on)
.ok
; Multi-hit attacks may or may not have 0 bp.
cp TWO_TO_FIVE_ATTACKS_EFFECT
2014-05-22 22:13:20 +00:00
jr z, .skipbp
cp $1e
2014-05-22 22:13:20 +00:00
jr z, .skipbp
; Calculate OHKO damage based on remaining HP.
cp OHKO_EFFECT
2015-03-31 18:50:49 +00:00
jp z, JumpToOHKOMoveEffect
2014-05-22 22:13:20 +00:00
; Don't calculate damage for moves that don't do any.
ld a, d ; base power
and a
ret z
.skipbp
xor a
ld hl, H_DIVIDEND
ldi [hl], a
ldi [hl], a
ld [hl], a
; Multiply level by 2
ld a, e ; level
add a
jr nc, .nc
push af
ld a, 1
ld [hl], a
pop af
.nc
inc hl
ldi [hl], a
; Divide by 5
ld a, 5
ldd [hl], a
push bc
ld b, 4
call Divide
pop bc
; Add 2
inc [hl]
inc [hl]
inc hl ; multiplier
; Multiply by attack base power
ld [hl], d
call Multiply
; Multiply by attack stat
ld [hl], b
call Multiply
; Divide by defender's defense stat
ld [hl], c
ld b, 4
call Divide
; Divide by 50
ld [hl], 50
ld b, 4
call Divide
2015-08-31 02:38:41 +00:00
ld hl, wDamage
2014-05-22 22:13:20 +00:00
ld b, [hl]
ld a, [H_QUOTIENT + 3]
add b
ld [H_QUOTIENT + 3], a
jr nc, .asm_3dfd0
ld a, [H_QUOTIENT + 2]
inc a
ld [H_QUOTIENT + 2], a
and a
jr z, .asm_3e004
.asm_3dfd0
ld a, [H_QUOTIENT]
ld b, a
ld a, [H_QUOTIENT + 1]
or a
jr nz, .asm_3e004
ld a, [H_QUOTIENT + 2]
cp 998 / $100
jr c, .asm_3dfe8
cp 998 / $100 + 1
jr nc, .asm_3e004
ld a, [H_QUOTIENT + 3]
cp 998 % $100
jr nc, .asm_3e004
.asm_3dfe8
inc hl
ld a, [H_QUOTIENT + 3]
ld b, [hl]
add b
ld [hld], a
ld a, [H_QUOTIENT + 2]
ld b, [hl]
adc b
ld [hl], a
jr c, .asm_3e004
ld a, [hl]
cp 998 / $100
jr c, .asm_3e00a
cp 998 / $100 + 1
jr nc, .asm_3e004
inc hl
ld a, [hld]
cp 998 % $100
jr c, .asm_3e00a
.asm_3e004
2015-01-04 16:47:21 +00:00
; cap at 997
2014-05-22 22:13:20 +00:00
ld a, 997 / $100
ld [hli], a
ld a, 997 % $100
ld [hld], a
.asm_3e00a
2015-01-04 16:47:21 +00:00
; add 2
2014-05-22 22:13:20 +00:00
inc hl
ld a, [hl]
add 2
ld [hld], a
jr nc, .done
inc [hl]
2015-01-23 03:05:13 +00:00
2014-05-22 22:13:20 +00:00
.done
2015-01-04 16:47:21 +00:00
; minimum damage is 1
2014-05-22 22:13:20 +00:00
ld a, 1
and a
ret
2016-06-12 00:24:04 +00:00
JumpToOHKOMoveEffect:
2014-08-09 05:39:13 +00:00
call JumpMoveEffect
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
dec a
ret
2016-06-12 00:24:04 +00:00
UnusedHighCriticalMoves:
2014-05-22 22:13:20 +00:00
db KARATE_CHOP
db RAZOR_LEAF
db CRABHAMMER
db SLASH
db $FF
; determines if attack is a critical hit
; azure heights claims "the fastest pokémon (who are,not coincidentally,
; among the most popular) tend to CH about 20 to 25% of the time."
2016-06-12 00:24:04 +00:00
CriticalHitTest:
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wCriticalHitOrOHKO], a
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld a, [wEnemyMonSpecies]
2016-06-12 04:30:05 +00:00
jr nz, .handleEnemy
ld a, [wBattleMonSpecies]
2016-06-12 04:30:05 +00:00
.handleEnemy
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
2015-08-31 02:38:41 +00:00
ld a, [wMonHBaseSpeed]
2014-05-22 22:13:20 +00:00
ld b, a
srl b ; (effective (base speed/2))
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld hl, wPlayerMovePower
ld de, wPlayerBattleStatus2
2014-05-22 22:13:20 +00:00
jr z, .calcCriticalHitProbability
2015-08-31 02:38:41 +00:00
ld hl, wEnemyMovePower
ld de, wEnemyBattleStatus2
.calcCriticalHitProbability
2014-05-22 22:13:20 +00:00
ld a, [hld] ; read base power from RAM
and a
ret z ; do nothing if zero
dec hl
ld c, [hl] ; read move id
ld a, [de]
2017-12-29 23:59:48 +00:00
bit GETTING_PUMPED, a ; test for focus energy
2014-05-22 22:13:20 +00:00
jr nz, .focusEnergyUsed ; bug: using focus energy causes a shift to the right instead of left,
; resulting in 1/4 the usual crit chance
sla b ; (effective (base speed/2)*2)
jr nc, .noFocusEnergyUsed
ld b, $ff ; cap at 255/256
jr .noFocusEnergyUsed
.focusEnergyUsed
srl b
.noFocusEnergyUsed
2015-01-04 16:47:21 +00:00
ld hl, HighCriticalMoves ; table of high critical hit moves
2014-05-22 22:13:20 +00:00
.Loop
ld a, [hli] ; read move from move table
cp c ; does it match the move about to be used?
jr z, .HighCritical ; if so, the move about to be used is a high critical hit ratio move
inc a ; move on to the next move, FF terminates loop
jr nz, .Loop ; check the next move in HighCriticalMoves
srl b ; /2 for regular move (effective (base speed / 2))
jr .SkipHighCritical ; continue as a normal move
.HighCritical
sla b ; *2 for high critical hit moves
jr nc, .noCarry
ld b, $ff ; cap at 255/256
.noCarry
sla b ; *4 for high critical move (effective (base speed/2)*8))
jr nc, .SkipHighCritical
ld b, $ff
.SkipHighCritical
2015-01-04 16:47:21 +00:00
call BattleRandom ; generates a random value, in "a"
2014-05-22 22:13:20 +00:00
rlc a
rlc a
rlc a
cp b ; check a against calculated crit rate
ret nc ; no critical hit if no borrow
ld a, $1
2015-01-04 16:47:21 +00:00
ld [wCriticalHitOrOHKO], a ; set critical hit flag
2014-05-22 22:13:20 +00:00
ret
; high critical hit moves
2016-06-12 00:24:04 +00:00
HighCriticalMoves:
2014-05-22 22:13:20 +00:00
db KARATE_CHOP
db RAZOR_LEAF
db CRABHAMMER
db SLASH
db $FF
; function to determine if Counter hits and if so, how much damage it does
2016-06-12 00:24:04 +00:00
HandleCounterMove:
2015-01-23 03:05:13 +00:00
; The variables checked by Counter are updated whenever the cursor points to a new move in the battle selection menu.
; This is irrelevant for the opponent's side outside of link battles, since the move selection is controlled by the AI.
; However, in the scenario where the player switches out and the opponent uses Counter,
2015-01-04 16:47:21 +00:00
; the outcome may be affected by the player's actions in the move selection menu prior to switching the Pokemon.
; This might also lead to desync glitches in link battles.
ld a, [H_WHOSETURN] ; whose turn
2014-05-22 22:13:20 +00:00
and a
; player's turn
ld hl, wEnemySelectedMove
ld de, wEnemyMovePower
ld a, [wPlayerSelectedMove]
jr z, .next
2014-05-22 22:13:20 +00:00
; enemy's turn
ld hl, wPlayerSelectedMove
ld de, wPlayerMovePower
ld a, [wEnemySelectedMove]
2014-05-22 22:13:20 +00:00
.next
cp COUNTER
2014-05-22 22:13:20 +00:00
ret nz ; return if not using Counter
ld a, $01
ld [wMoveMissed], a ; initialize the move missed variable to true (it is set to false below if the move hits)
ld a, [hl]
cp COUNTER
2015-01-04 16:47:21 +00:00
ret z ; miss if the opponent's last selected move is Counter.
ld a, [de]
2014-05-22 22:13:20 +00:00
and a
2015-01-04 16:47:21 +00:00
ret z ; miss if the opponent's last selected move's Base Power is 0.
; check if the move the target last selected was Normal or Fighting type
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
2014-05-22 22:13:20 +00:00
and a ; normal type
jr z, .counterableType
cp FIGHTING
jr z, .counterableType
2014-05-22 22:13:20 +00:00
; if the move wasn't Normal or Fighting type, miss
xor a
ret
.counterableType
ld hl, wDamage
ld a, [hli]
2014-05-22 22:13:20 +00:00
or [hl]
2015-01-04 16:47:21 +00:00
ret z ; If we made it here, Counter still misses if the last move used in battle did no damage to its target.
2015-08-31 02:38:41 +00:00
; wDamage is shared by both players, so Counter may strike back damage dealt by the Counter user itself
; if the conditions meet, even though 99% of the times damage will come from the target.
2015-01-04 16:47:21 +00:00
; if it did damage, double it
ld a, [hl]
2014-05-22 22:13:20 +00:00
add a
ldd [hl], a
ld a, [hl]
2014-05-22 22:13:20 +00:00
adc a
ld [hl], a
jr nc, .noCarry
2014-05-22 22:13:20 +00:00
; damage is capped at 0xFFFF
ld a, $ff
ld [hli], a
ld [hl], a
2014-05-22 22:13:20 +00:00
.noCarry
xor a
ld [wMoveMissed], a
2014-05-22 22:13:20 +00:00
call MoveHitTest ; do the normal move hit test in addition to Counter's special rules
xor a
ret
2016-06-12 00:24:04 +00:00
ApplyAttackToEnemyPokemon:
ld a, [wPlayerMoveEffect]
cp OHKO_EFFECT
jr z, ApplyDamageToEnemyPokemon
cp SUPER_FANG_EFFECT
jr z, .superFangEffect
cp SPECIAL_DAMAGE_EFFECT
jr z, .specialDamage
ld a, [wPlayerMovePower]
2014-05-22 22:13:20 +00:00
and a
jp z, ApplyAttackToEnemyPokemonDone ; no attack to apply if base power is 0
2014-05-22 22:13:20 +00:00
jr ApplyDamageToEnemyPokemon
.superFangEffect
; set the damage to half the target's HP
ld hl, wEnemyMonHP
ld de, wDamage
ld a, [hli]
2014-05-22 22:13:20 +00:00
srl a
ld [de], a
2014-05-22 22:13:20 +00:00
inc de
ld b, a
ld a, [hl]
2014-05-22 22:13:20 +00:00
rr a
ld [de], a
2014-05-22 22:13:20 +00:00
or b
jr nz, ApplyDamageToEnemyPokemon
2014-05-22 22:13:20 +00:00
; make sure Super Fang's damage is always at least 1
ld a, $01
ld [de], a
2014-05-22 22:13:20 +00:00
jr ApplyDamageToEnemyPokemon
.specialDamage
ld hl, wBattleMonLevel
ld a, [hl]
ld b, a ; Seismic Toss deals damage equal to the user's level
ld a, [wPlayerMoveNum]
cp SEISMIC_TOSS
jr z, .storeDamage
cp NIGHT_SHADE
jr z, .storeDamage
ld b, SONICBOOM_DAMAGE ; 20
cp SONICBOOM
jr z, .storeDamage
ld b, DRAGON_RAGE_DAMAGE ; 40
cp DRAGON_RAGE
jr z, .storeDamage
2014-05-22 22:13:20 +00:00
; Psywave
ld a, [hl]
ld b, a
2014-05-22 22:13:20 +00:00
srl a
add b
ld b, a ; b = level * 1.5
2014-05-22 22:13:20 +00:00
; loop until a random number in the range [1, b) is found
.loop
call BattleRandom
2014-05-22 22:13:20 +00:00
and a
jr z, .loop
2014-05-22 22:13:20 +00:00
cp b
jr nc, .loop
ld b, a
2015-01-04 16:47:21 +00:00
.storeDamage ; store damage value at b
ld hl, wDamage
2014-05-22 22:13:20 +00:00
xor a
ld [hli], a
ld a, b
ld [hl], a
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ApplyDamageToEnemyPokemon:
ld hl, wDamage
ld a, [hli]
ld b, a
ld a, [hl]
2014-05-22 22:13:20 +00:00
or b
jr z, ApplyAttackToEnemyPokemonDone ; we're done if damage is 0
ld a, [wEnemyBattleStatus2]
bit HAS_SUBSTITUTE_UP, a ; does the enemy have a substitute?
jp nz, AttackSubstitute
2014-05-22 22:13:20 +00:00
; subtract the damage from the pokemon's current HP
; also, save the current HP at wHPBarOldHP
ld a, [hld]
ld b, a
ld a, [wEnemyMonHP + 1]
ld [wHPBarOldHP], a
2014-05-22 22:13:20 +00:00
sub b
ld [wEnemyMonHP + 1], a
ld a, [hl]
ld b, a
ld a, [wEnemyMonHP]
ld [wHPBarOldHP+1], a
2014-05-22 22:13:20 +00:00
sbc b
ld [wEnemyMonHP], a
jr nc, .animateHpBar
2015-08-31 02:38:41 +00:00
; if more damage was done than the current HP, zero the HP and set the damage (wDamage)
2014-05-22 22:13:20 +00:00
; equal to how much HP the pokemon had before the attack
ld a, [wHPBarOldHP+1]
ld [hli], a
ld a, [wHPBarOldHP]
ld [hl], a
xor a
ld hl, wEnemyMonHP
ld [hli], a
ld [hl], a
2014-05-22 22:13:20 +00:00
.animateHpBar
ld hl, wEnemyMonMaxHP
ld a, [hli]
ld [wHPBarMaxHP+1], a
ld a, [hl]
ld [wHPBarMaxHP], a
ld hl, wEnemyMonHP
ld a, [hli]
ld [wHPBarNewHP+1], a
ld a, [hl]
ld [wHPBarNewHP], a
2015-07-18 20:52:03 +00:00
coord hl, 2, 2
2014-05-22 22:13:20 +00:00
xor a
ld [wHPBarType], a
predef UpdateHPBar2 ; animate the HP bar shortening
2016-06-12 00:24:04 +00:00
ApplyAttackToEnemyPokemonDone:
2014-08-09 05:39:13 +00:00
jp DrawHUDsAndHPBars
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ApplyAttackToPlayerPokemon:
ld a, [wEnemyMoveEffect]
cp OHKO_EFFECT
jr z, ApplyDamageToPlayerPokemon
cp SUPER_FANG_EFFECT
jr z, .superFangEffect
cp SPECIAL_DAMAGE_EFFECT
jr z, .specialDamage
ld a, [wEnemyMovePower]
2014-05-22 22:13:20 +00:00
and a
jp z, ApplyAttackToPlayerPokemonDone
2014-05-22 22:13:20 +00:00
jr ApplyDamageToPlayerPokemon
.superFangEffect
; set the damage to half the target's HP
ld hl, wBattleMonHP
ld de, wDamage
ld a, [hli]
2014-05-22 22:13:20 +00:00
srl a
ld [de], a
2014-05-22 22:13:20 +00:00
inc de
ld b, a
ld a, [hl]
2014-05-22 22:13:20 +00:00
rr a
ld [de], a
2014-05-22 22:13:20 +00:00
or b
jr nz, ApplyDamageToPlayerPokemon
2014-05-22 22:13:20 +00:00
; make sure Super Fang's damage is always at least 1
ld a, $01
ld [de], a
2014-05-22 22:13:20 +00:00
jr ApplyDamageToPlayerPokemon
.specialDamage
ld hl, wEnemyMonLevel
ld a, [hl]
ld b, a
ld a, [wEnemyMoveNum]
cp SEISMIC_TOSS
jr z, .storeDamage
cp NIGHT_SHADE
jr z, .storeDamage
ld b, SONICBOOM_DAMAGE
cp SONICBOOM
jr z, .storeDamage
ld b, DRAGON_RAGE_DAMAGE
cp DRAGON_RAGE
jr z, .storeDamage
2014-05-22 22:13:20 +00:00
; Psywave
ld a, [hl]
ld b, a
2014-05-22 22:13:20 +00:00
srl a
add b
ld b, a ; b = attacker's level * 1.5
2014-05-22 22:13:20 +00:00
; loop until a random number in the range [0, b) is found
; this differs from the range when the player attacks, which is [1, b)
; it's possible for the enemy to do 0 damage with Psywave, but the player always does at least 1 damage
.loop
call BattleRandom
2014-05-22 22:13:20 +00:00
cp b
jr nc, .loop
ld b, a
2014-05-22 22:13:20 +00:00
.storeDamage
ld hl, wDamage
2014-05-22 22:13:20 +00:00
xor a
ld [hli], a
ld a, b
ld [hl], a
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ApplyDamageToPlayerPokemon:
ld hl, wDamage
ld a, [hli]
ld b, a
ld a, [hl]
2014-05-22 22:13:20 +00:00
or b
jr z, ApplyAttackToPlayerPokemonDone ; we're done if damage is 0
ld a, [wPlayerBattleStatus2]
bit HAS_SUBSTITUTE_UP, a ; does the player have a substitute?
jp nz, AttackSubstitute
2014-05-22 22:13:20 +00:00
; subtract the damage from the pokemon's current HP
; also, save the current HP at wHPBarOldHP and the new HP at wHPBarNewHP
ld a, [hld]
ld b, a
ld a, [wBattleMonHP + 1]
ld [wHPBarOldHP], a
2014-05-22 22:13:20 +00:00
sub b
ld [wBattleMonHP + 1], a
ld [wHPBarNewHP], a
ld b, [hl]
ld a, [wBattleMonHP]
ld [wHPBarOldHP+1], a
2014-05-22 22:13:20 +00:00
sbc b
ld [wBattleMonHP], a
ld [wHPBarNewHP+1], a
jr nc, .animateHpBar
2015-08-31 02:38:41 +00:00
; if more damage was done than the current HP, zero the HP and set the damage (wDamage)
2014-05-22 22:13:20 +00:00
; equal to how much HP the pokemon had before the attack
ld a, [wHPBarOldHP+1]
ld [hli], a
ld a, [wHPBarOldHP]
ld [hl], a
xor a
ld hl, wBattleMonHP
ld [hli], a
ld [hl], a
ld hl, wHPBarNewHP
ld [hli], a
ld [hl], a
2014-05-22 22:13:20 +00:00
.animateHpBar
ld hl, wBattleMonMaxHP
ld a, [hli]
ld [wHPBarMaxHP+1], a
ld a, [hl]
ld [wHPBarMaxHP], a
2015-07-18 20:52:03 +00:00
coord hl, 10, 9
ld a, $01
ld [wHPBarType], a
predef UpdateHPBar2 ; animate the HP bar shortening
2016-06-12 04:30:05 +00:00
ApplyAttackToPlayerPokemonDone:
2014-08-09 05:39:13 +00:00
jp DrawHUDsAndHPBars
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
AttackSubstitute:
2015-01-04 16:47:21 +00:00
; Unlike the two ApplyAttackToPokemon functions, Attack Substitute is shared by player and enemy.
; Self-confusion damage as well as Hi-Jump Kick and Jump Kick recoil cause a momentary turn swap before being applied.
2015-06-11 22:41:33 +00:00
; If the user has a Substitute up and would take damage because of that,
; damage will be applied to the other player's Substitute.
2015-06-11 22:41:33 +00:00
; Normal recoil such as from Double-Edge isn't affected by this glitch,
; because this function is never called in that case.
2015-01-04 16:47:21 +00:00
ld hl, SubstituteTookDamageText
2014-05-22 22:13:20 +00:00
call PrintText
; values for player turn
ld de, wEnemySubstituteHP
ld bc, wEnemyBattleStatus2
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .applyDamageToSubstitute
2014-05-22 22:13:20 +00:00
; values for enemy turn
ld de, wPlayerSubstituteHP
ld bc, wPlayerBattleStatus2
2014-05-22 22:13:20 +00:00
.applyDamageToSubstitute
ld hl, wDamage
ld a, [hli]
2014-05-22 22:13:20 +00:00
and a
jr nz, .substituteBroke ; damage > 0xFF always breaks substitutes
2014-05-22 22:13:20 +00:00
; subtract damage from HP of substitute
ld a, [de]
2014-05-22 22:13:20 +00:00
sub [hl]
ld [de], a
2014-05-22 22:13:20 +00:00
ret nc
.substituteBroke
2015-08-31 02:38:41 +00:00
; If the target's Substitute breaks, wDamage isn't updated with the amount of HP
; the Substitute had before being attacked.
ld h, b
ld l, c
res HAS_SUBSTITUTE_UP, [hl] ; unset the substitute bit
ld hl, SubstituteBrokeText
2014-05-22 22:13:20 +00:00
call PrintText
; flip whose turn it is for the next function call
ld a, [H_WHOSETURN]
xor $01
ld [H_WHOSETURN], a
2015-07-12 22:51:04 +00:00
callab HideSubstituteShowMonAnim ; animate the substitute breaking
2014-05-22 22:13:20 +00:00
; flip the turn back to the way it was
ld a, [H_WHOSETURN]
xor $01
ld [H_WHOSETURN], a
ld hl, wPlayerMoveEffect ; value for player's turn
2014-05-22 22:13:20 +00:00
and a
jr z, .nullifyEffect
ld hl, wEnemyMoveEffect ; value for enemy's turn
2014-05-22 22:13:20 +00:00
.nullifyEffect
xor a
ld [hl], a ; zero the effect of the attacker's move
2014-08-09 05:39:13 +00:00
jp DrawHUDsAndHPBars
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
SubstituteTookDamageText:
2014-05-22 22:13:20 +00:00
TX_FAR _SubstituteTookDamageText
db "@"
2016-06-12 00:24:04 +00:00
SubstituteBrokeText:
2014-05-22 22:13:20 +00:00
TX_FAR _SubstituteBrokeText
db "@"
; this function raises the attack modifier of a pokemon using Rage when that pokemon is attacked
2016-06-12 00:24:04 +00:00
HandleBuildingRage:
2014-05-22 22:13:20 +00:00
; values for the player turn
ld hl, wEnemyBattleStatus2
ld de, wEnemyMonStatMods
ld bc, wEnemyMoveNum
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .next
2014-05-22 22:13:20 +00:00
; values for the enemy turn
ld hl, wPlayerBattleStatus2
ld de, wPlayerMonStatMods
ld bc, wPlayerMoveNum
2014-05-22 22:13:20 +00:00
.next
bit USING_RAGE, [hl] ; is the pokemon being attacked under the effect of Rage?
2014-05-22 22:13:20 +00:00
ret z ; return if not
ld a, [de]
cp $0d ; maximum stat modifier value
2014-05-22 22:13:20 +00:00
ret z ; return if attack modifier is already maxed
ld a, [H_WHOSETURN]
xor $01 ; flip turn for the stat modifier raising function
ld [H_WHOSETURN], a
; temporarily change the target pokemon's move to $00 and the effect to the one
2014-05-22 22:13:20 +00:00
; that causes the attack modifier to go up one stage
ld h, b
ld l, c
ld [hl], $00 ; null move number
2014-05-22 22:13:20 +00:00
inc hl
ld [hl], ATTACK_UP1_EFFECT
2014-05-22 22:13:20 +00:00
push hl
ld hl, BuildingRageText
2014-05-22 22:13:20 +00:00
call PrintText
call StatModifierUpEffect ; stat modifier raising function
pop hl
xor a
ldd [hl], a ; null move effect
ld a, RAGE
ld [hl], a ; restore the target pokemon's move number to Rage
ld a, [H_WHOSETURN]
xor $01 ; flip turn back to the way it was
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
BuildingRageText:
2014-05-22 22:13:20 +00:00
TX_FAR _BuildingRageText
db "@"
; copy last move for Mirror Move
; sets zero flag on failure and unsets zero flag on success
2016-06-12 00:24:04 +00:00
MirrorMoveCopyMove:
; Mirror Move makes use of ccf1 (wPlayerUsedMove) and ccf2 (wEnemyUsedMove) addresses,
; which are mainly used to print the "[Pokemon] used [Move]" text.
2015-01-04 16:47:21 +00:00
; Both are set to 0 whenever a new Pokemon is sent out
; ccf1 is also set to 0 whenever the player is fast asleep or frozen solid.
; ccf2 is also set to 0 whenever the enemy is fast asleep or frozen solid.
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
; values for player turn
ld a, [wEnemyUsedMove]
ld hl, wPlayerSelectedMove
ld de, wPlayerMoveNum
jr z, .next
2014-05-22 22:13:20 +00:00
; values for enemy turn
ld a, [wPlayerUsedMove]
ld de, wEnemyMoveNum
ld hl, wEnemySelectedMove
2014-05-22 22:13:20 +00:00
.next
ld [hl], a
cp MIRROR_MOVE ; did the target Pokemon last use Mirror Move, and miss?
jr z, .mirrorMoveFailed
and a ; has the target selected any move yet?
jr nz, ReloadMoveData
2014-05-22 22:13:20 +00:00
.mirrorMoveFailed
ld hl, MirrorMoveFailedText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
ret
2016-06-12 00:24:04 +00:00
MirrorMoveFailedText:
2014-05-22 22:13:20 +00:00
TX_FAR _MirrorMoveFailedText
db "@"
; function used to reload move data for moves like Mirror Move and Metronome
2016-06-12 00:24:04 +00:00
ReloadMoveData:
ld [wd11e], a
2014-05-22 22:13:20 +00:00
dec a
ld hl, Moves
ld bc, MoveEnd - Moves
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, BANK(Moves)
2014-05-22 22:13:20 +00:00
call FarCopyData ; copy the move's stats
call IncrementMovePP
; the follow two function calls are used to reload the move name
call GetMoveName
call CopyStringToCF4B
ld a, $01
2014-05-22 22:13:20 +00:00
and a
ret
; function that picks a random move for metronome
2016-06-12 00:24:04 +00:00
MetronomePickMove:
2014-05-22 22:13:20 +00:00
xor a
ld [wAnimationType], a
ld a, METRONOME
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation ; play Metronome's animation
; values for player turn
ld de, wPlayerMoveNum
ld hl, wPlayerSelectedMove
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .pickMoveLoop
2014-05-22 22:13:20 +00:00
; values for enemy turn
ld de, wEnemyMoveNum
ld hl, wEnemySelectedMove
2014-05-22 22:13:20 +00:00
; loop to pick a random number in the range [1, $a5) to be the move used by Metronome
.pickMoveLoop
call BattleRandom
2014-05-22 22:13:20 +00:00
and a
jr z, .pickMoveLoop
cp NUM_ATTACKS + 1 ; max normal move number + 1 (this is Struggle's move number)
jr nc, .pickMoveLoop
cp METRONOME
jr z, .pickMoveLoop
ld [hl], a
2014-05-22 22:13:20 +00:00
jr ReloadMoveData
; this function increments the current move's PP
; it's used to prevent moves that run another move within the same turn
; (like Mirror Move and Metronome) from losing 2 PP
2016-06-12 00:24:04 +00:00
IncrementMovePP:
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
; values for player turn
ld hl, wBattleMonPP
ld de, wPartyMon1PP
ld a, [wPlayerMoveListIndex]
jr z, .next
2014-05-22 22:13:20 +00:00
; values for enemy turn
ld hl, wEnemyMonPP
ld de, wEnemyMon1PP
ld a, [wEnemyMoveListIndex]
2014-05-22 22:13:20 +00:00
.next
ld b, $00
ld c, a
add hl, bc
2014-05-22 22:13:20 +00:00
inc [hl] ; increment PP in the currently battling pokemon memory location
ld h, d
ld l, e
add hl, bc
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld a, [wPlayerMonNumber] ; value for player turn
jr z, .updatePP
ld a, [wEnemyMonPartyPos] ; value for enemy turn
2015-01-20 19:21:16 +00:00
.updatePP
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
inc [hl] ; increment PP in the party memory location
ret
; function to adjust the base damage of an attack to account for type effectiveness
2016-06-12 00:24:04 +00:00
AdjustDamageForMoveType:
2014-05-22 22:13:20 +00:00
; values for player turn
ld hl, wBattleMonType
ld a, [hli]
ld b, a ; b = type 1 of attacker
ld c, [hl] ; c = type 2 of attacker
ld hl, wEnemyMonType
ld a, [hli]
ld d, a ; d = type 1 of defender
ld e, [hl] ; e = type 2 of defender
ld a, [wPlayerMoveType]
ld [wMoveType], a
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .next
2014-05-22 22:13:20 +00:00
; values for enemy turn
ld hl, wEnemyMonType
ld a, [hli]
ld b, a ; b = type 1 of attacker
ld c, [hl] ; c = type 2 of attacker
ld hl, wBattleMonType
ld a, [hli]
ld d, a ; d = type 1 of defender
ld e, [hl] ; e = type 2 of defender
ld a, [wEnemyMoveType]
ld [wMoveType], a
2014-05-22 22:13:20 +00:00
.next
ld a, [wMoveType]
2014-05-22 22:13:20 +00:00
cp b ; does the move type match type 1 of the attacker?
jr z, .sameTypeAttackBonus
2014-05-22 22:13:20 +00:00
cp c ; does the move type match type 2 of the attacker?
jr z, .sameTypeAttackBonus
2014-05-22 22:13:20 +00:00
jr .skipSameTypeAttackBonus
.sameTypeAttackBonus
; if the move type matches one of the attacker's types
ld hl, wDamage + 1
ld a, [hld]
ld h, [hl]
ld l, a ; hl = damage
ld b, h
ld c, l ; bc = damage
2014-05-22 22:13:20 +00:00
srl b
rr c ; bc = floor(0.5 * damage)
add hl, bc ; hl = floor(1.5 * damage)
2014-05-22 22:13:20 +00:00
; store damage
ld a, h
ld [wDamage], a
ld a, l
ld [wDamage + 1], a
ld hl, wDamageMultipliers
set 7, [hl]
2014-05-22 22:13:20 +00:00
.skipSameTypeAttackBonus
ld a, [wMoveType]
ld b, a
ld hl, TypeEffects
2014-05-22 22:13:20 +00:00
.loop
ld a, [hli] ; a = "attacking type" of the current type pair
cp $ff
jr z, .done
2014-05-22 22:13:20 +00:00
cp b ; does move type match "attacking type"?
jr nz, .nextTypePair
ld a, [hl] ; a = "defending type" of the current type pair
2014-05-22 22:13:20 +00:00
cp d ; does type 1 of defender match "defending type"?
jr z, .matchingPairFound
2014-05-22 22:13:20 +00:00
cp e ; does type 2 of defender match "defending type"?
jr z, .matchingPairFound
2014-05-22 22:13:20 +00:00
jr .nextTypePair
.matchingPairFound
; if the move type matches the "attacking type" and one of the defender's types matches the "defending type"
push hl
push bc
inc hl
ld a, [wDamageMultipliers]
and $80
ld b, a
ld a, [hl] ; a = damage multiplier
ld [H_MULTIPLIER], a
2014-05-22 22:13:20 +00:00
add b
ld [wDamageMultipliers], a
xor a
ld [H_MULTIPLICAND], a
ld hl, wDamage
ld a, [hli]
ld [H_MULTIPLICAND + 1], a
ld a, [hld]
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
call Multiply
ld a, 10
ld [H_DIVISOR], a
ld b, $04
2014-05-22 22:13:20 +00:00
call Divide
ld a, [H_QUOTIENT + 2]
ld [hli], a
ld b, a
ld a, [H_QUOTIENT + 3]
ld [hl], a
2014-05-22 22:13:20 +00:00
or b ; is damage 0?
jr nz, .skipTypeImmunity
2014-05-22 22:13:20 +00:00
.typeImmunity
; if damage is 0, make the move miss
2015-01-04 16:47:21 +00:00
; this only occurs if a move that would do 2 or 3 damage is 0.25x effective against the target
2014-05-22 22:13:20 +00:00
inc a
ld [wMoveMissed], a
2014-05-22 22:13:20 +00:00
.skipTypeImmunity
pop bc
pop hl
.nextTypePair
inc hl
inc hl
jp .loop
.done
ret
; function to tell how effective the type of an enemy attack is on the player's current pokemon
; this doesn't take into account the effects that dual types can have
; (e.g. 4x weakness / resistance, weaknesses and resistances canceling)
2015-08-07 12:20:37 +00:00
; the result is stored in [wTypeEffectiveness]
2014-05-22 22:13:20 +00:00
; ($05 is not very effective, $10 is neutral, $14 is super effective)
; as far is can tell, this is only used once in some AI code to help decide which move to use
2016-06-12 00:24:04 +00:00
AIGetTypeEffectiveness:
ld a, [wEnemyMoveType]
ld d, a ; d = type of enemy move
ld hl, wBattleMonType
ld b, [hl] ; b = type 1 of player's pokemon
2014-05-22 22:13:20 +00:00
inc hl
ld c, [hl] ; c = type 2 of player's pokemon
ld a, $10
ld [wTypeEffectiveness], a ; initialize to neutral effectiveness
ld hl, TypeEffects
2014-05-22 22:13:20 +00:00
.loop
ld a, [hli]
cp $ff
2014-05-22 22:13:20 +00:00
ret z
2015-08-07 12:20:37 +00:00
cp d ; match the type of the move
jr nz, .nextTypePair1
ld a, [hli]
2015-08-07 12:20:37 +00:00
cp b ; match with type 1 of pokemon
jr z, .done
2015-08-07 12:20:37 +00:00
cp c ; or match with type 2 of pokemon
jr z, .done
2014-05-22 22:13:20 +00:00
jr .nextTypePair2
.nextTypePair1
inc hl
.nextTypePair2
inc hl
jr .loop
.done
ld a, [hl]
ld [wTypeEffectiveness], a ; store damage multiplier
2014-05-22 22:13:20 +00:00
ret
INCLUDE "data/type_effects.asm"
; some tests that need to pass for a move to hit
2016-06-12 00:24:04 +00:00
MoveHitTest:
2014-05-22 22:13:20 +00:00
; player's turn
ld hl, wEnemyBattleStatus1
ld de, wPlayerMoveEffect
ld bc, wEnemyMonStatus
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .dreamEaterCheck
2014-05-22 22:13:20 +00:00
; enemy's turn
ld hl, wPlayerBattleStatus1
ld de, wEnemyMoveEffect
ld bc, wBattleMonStatus
2014-05-22 22:13:20 +00:00
.dreamEaterCheck
ld a, [de]
cp DREAM_EATER_EFFECT
jr nz, .swiftCheck
ld a, [bc]
and SLP ; is the target pokemon sleeping?
jp z, .moveMissed
2014-05-22 22:13:20 +00:00
.swiftCheck
ld a, [de]
cp SWIFT_EFFECT
2014-05-22 22:13:20 +00:00
ret z ; Swift never misses (interestingly, Azure Heights lists this is a myth, but it appears to be true)
call CheckTargetSubstitute ; substitute check (note that this overwrites a)
jr z, .checkForDigOrFlyStatus
2014-05-22 22:13:20 +00:00
; this code is buggy. it's supposed to prevent HP draining moves from working on substitutes.
; since $7b79 overwrites a with either $00 or $01, it never works.
cp DRAIN_HP_EFFECT
jp z, .moveMissed
cp DREAM_EATER_EFFECT
jp z, .moveMissed
2014-05-22 22:13:20 +00:00
.checkForDigOrFlyStatus
bit INVULNERABLE, [hl]
jp nz, .moveMissed
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr nz, .enemyTurn
2014-05-22 22:13:20 +00:00
.playerTurn
; this checks if the move effect is disallowed by mist
ld a, [wPlayerMoveEffect]
cp ATTACK_DOWN1_EFFECT
jr c, .skipEnemyMistCheck
cp HAZE_EFFECT + 1
jr c, .enemyMistCheck
cp ATTACK_DOWN2_EFFECT
jr c, .skipEnemyMistCheck
cp REFLECT_EFFECT + 1
jr c, .enemyMistCheck
2014-05-22 22:13:20 +00:00
jr .skipEnemyMistCheck
.enemyMistCheck
; if move effect is from $12 to $19 inclusive or $3a to $41 inclusive
; i.e. the following moves
; GROWL, TAIL WHIP, LEER, STRING SHOT, SAND-ATTACK, SMOKESCREEN, KINESIS,
; FLASH, CONVERSION*, HAZE*, SCREECH, LIGHT SCREEN*, REFLECT*
2014-05-22 22:13:20 +00:00
; the moves that are marked with an asterisk are not affected since this
; function is not called when those moves are used
ld a, [wEnemyBattleStatus2]
bit PROTECTED_BY_MIST, a ; is mon protected by mist?
jp nz, .moveMissed
2014-05-22 22:13:20 +00:00
.skipEnemyMistCheck
ld a, [wPlayerBattleStatus2]
bit USING_X_ACCURACY, a ; is the player using X Accuracy?
2014-05-22 22:13:20 +00:00
ret nz ; if so, always hit regardless of accuracy/evasion
jr .calcHitChance
.enemyTurn
ld a, [wEnemyMoveEffect]
cp ATTACK_DOWN1_EFFECT
jr c, .skipPlayerMistCheck
cp HAZE_EFFECT + 1
jr c, .playerMistCheck
cp ATTACK_DOWN2_EFFECT
jr c, .skipPlayerMistCheck
cp REFLECT_EFFECT + 1
jr c, .playerMistCheck
2014-05-22 22:13:20 +00:00
jr .skipPlayerMistCheck
.playerMistCheck
; similar to enemy mist check
ld a, [wPlayerBattleStatus2]
bit PROTECTED_BY_MIST, a ; is mon protected by mist?
jp nz, .moveMissed
2014-05-22 22:13:20 +00:00
.skipPlayerMistCheck
ld a, [wEnemyBattleStatus2]
bit USING_X_ACCURACY, a ; is the enemy using X Accuracy?
2014-05-22 22:13:20 +00:00
ret nz ; if so, always hit regardless of accuracy/evasion
.calcHitChance
call CalcHitChance ; scale the move accuracy according to attacker's accuracy and target's evasion
ld a, [wPlayerMoveAccuracy]
ld b, a
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .doAccuracyCheck
ld a, [wEnemyMoveAccuracy]
ld b, a
2014-05-22 22:13:20 +00:00
.doAccuracyCheck
; if the random number generated is greater than or equal to the scaled accuracy, the move misses
; note that this means that even the highest accuracy is still just a 255/256 chance, not 100%
call BattleRandom
2014-05-22 22:13:20 +00:00
cp b
jr nc, .moveMissed
2014-05-22 22:13:20 +00:00
ret
.moveMissed
xor a
ld hl, wDamage ; zero the damage
ld [hli], a
ld [hl], a
2014-05-22 22:13:20 +00:00
inc a
ld [wMoveMissed], a
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .playerTurn2
2014-05-22 22:13:20 +00:00
.enemyTurn2
ld hl, wEnemyBattleStatus1
res USING_TRAPPING_MOVE, [hl] ; end multi-turn attack e.g. wrap
2014-05-22 22:13:20 +00:00
ret
.playerTurn2
ld hl, wPlayerBattleStatus1
res USING_TRAPPING_MOVE, [hl] ; end multi-turn attack e.g. wrap
2014-05-22 22:13:20 +00:00
ret
; values for player turn
2016-06-12 00:24:04 +00:00
CalcHitChance:
ld hl, wPlayerMoveAccuracy
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld a, [wPlayerMonAccuracyMod]
ld b, a
ld a, [wEnemyMonEvasionMod]
ld c, a
jr z, .next
2014-05-22 22:13:20 +00:00
; values for enemy turn
ld hl, wEnemyMoveAccuracy
ld a, [wEnemyMonAccuracyMod]
ld b, a
ld a, [wPlayerMonEvasionMod]
ld c, a
2014-05-22 22:13:20 +00:00
.next
ld a, $0e
2014-05-22 22:13:20 +00:00
sub c
ld c, a ; c = 14 - EVASIONMOD (this "reflects" the value over 7, so that an increase in the target's evasion
; decreases the hit chance instead of increasing the hit chance)
2014-05-22 22:13:20 +00:00
; zero the high bytes of the multiplicand
xor a
ld [H_MULTIPLICAND], a
ld [H_MULTIPLICAND + 1], a
ld a, [hl]
ld [H_MULTIPLICAND + 2], a ; set multiplicand to move accuracy
2014-05-22 22:13:20 +00:00
push hl
ld d, $02 ; loop has two iterations
; loop to do the calculations, the first iteration multiplies by the accuracy ratio and
; the second iteration multiplies by the evasion ratio
2014-05-22 22:13:20 +00:00
.loop
push bc
ld hl, StatModifierRatios ; stat modifier ratios
2014-05-22 22:13:20 +00:00
dec b
sla b
ld c, b
ld b, $00
add hl, bc ; hl = address of stat modifier ratio
2014-05-22 22:13:20 +00:00
pop bc
ld a, [hli]
ld [H_MULTIPLIER], a ; set multiplier to the numerator of the ratio
2014-05-22 22:13:20 +00:00
call Multiply
ld a, [hl]
ld [H_DIVISOR], a ; set divisor to the the denominator of the ratio
; (the dividend is the product of the previous multiplication)
ld b, $04 ; number of bytes in the dividend
2014-05-22 22:13:20 +00:00
call Divide
ld a, [H_QUOTIENT + 3]
ld b, a
ld a, [H_QUOTIENT + 2]
2014-05-22 22:13:20 +00:00
or b
jp nz, .nextCalculation
2014-05-22 22:13:20 +00:00
; make sure the result is always at least one
ld [H_QUOTIENT + 2], a
ld a, $01
ld [H_QUOTIENT + 3], a
2014-05-22 22:13:20 +00:00
.nextCalculation
ld b, c
2014-05-22 22:13:20 +00:00
dec d
jr nz, .loop
ld a, [H_QUOTIENT + 2]
2014-05-22 22:13:20 +00:00
and a ; is the calculated hit chance over 0xFF?
ld a, [H_QUOTIENT + 3]
jr z, .storeAccuracy
2014-05-22 22:13:20 +00:00
; if calculated hit chance over 0xFF
ld a, $ff ; set the hit chance to 0xFF
2014-05-22 22:13:20 +00:00
.storeAccuracy
pop hl
ld [hl], a ; store the hit chance in the move accuracy variable
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; multiplies damage by a random percentage from ~85% to 100%
2016-06-12 00:24:04 +00:00
RandomizeDamage:
2015-08-31 02:38:41 +00:00
ld hl, wDamage
2014-05-22 22:13:20 +00:00
ld a, [hli]
and a
2014-08-09 05:39:13 +00:00
jr nz, .DamageGreaterThanOne
2014-05-22 22:13:20 +00:00
ld a, [hl]
2014-08-09 05:39:13 +00:00
cp 2
2015-01-04 16:47:21 +00:00
ret c ; return if damage is equal to 0 or 1
2014-08-09 05:39:13 +00:00
.DamageGreaterThanOne
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND], a
2014-05-22 22:13:20 +00:00
dec hl
ld a, [hli]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 2], a
; loop until a random number greater than or equal to 217 is generated
.loop
call BattleRandom
2014-05-22 22:13:20 +00:00
rrca
2014-08-09 05:39:13 +00:00
cp 217
jr c, .loop
ld [H_MULTIPLIER], a
call Multiply ; multiply damage by the random number, which is in the range [217, 255]
ld a, 255
ld [H_DIVISOR], a
2014-05-22 22:13:20 +00:00
ld b, $4
2014-08-09 05:39:13 +00:00
call Divide ; divide the result by 255
; store the modified damage
ld a, [H_QUOTIENT + 2]
2015-08-31 02:38:41 +00:00
ld hl, wDamage
2014-05-22 22:13:20 +00:00
ld [hli], a
2014-08-09 05:39:13 +00:00
ld a, [H_QUOTIENT + 3]
2014-05-22 22:13:20 +00:00
ld [hl], a
ret
; for more detailed commentary, see equivalent function for player side (ExecutePlayerMove)
2016-06-12 00:24:04 +00:00
ExecuteEnemyMove:
2014-08-09 05:39:13 +00:00
ld a, [wEnemySelectedMove]
2014-05-22 22:13:20 +00:00
inc a
jp z, ExecuteEnemyMoveDone
2014-05-22 22:13:20 +00:00
call PrintGhostText
jp z, ExecuteEnemyMoveDone
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
jr nz, .executeEnemyMove
2014-05-22 22:13:20 +00:00
ld b, $1
2015-02-07 10:43:08 +00:00
ld a, [wSerialExchangeNybbleReceiveData]
2016-10-29 08:44:13 +00:00
cp LINKBATTLE_STRUGGLE
jr z, .executeEnemyMove
2016-10-29 08:44:13 +00:00
cp 4
2014-05-22 22:13:20 +00:00
ret nc
.executeEnemyMove
2015-03-31 18:40:22 +00:00
ld hl, wAILayer2Encouragement
2014-05-22 22:13:20 +00:00
inc [hl]
xor a
2015-08-31 02:38:41 +00:00
ld [wMoveMissed], a
2015-03-31 18:28:42 +00:00
ld [wMoveDidntMiss], a
2014-05-22 22:13:20 +00:00
ld a, $a
2015-03-31 18:28:42 +00:00
ld [wDamageMultipliers], a
2014-08-09 05:39:13 +00:00
call CheckEnemyStatusConditions
jr nz, .enemyHasNoSpecialConditions
jp hl
.enemyHasNoSpecialConditions
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
bit CHARGING_UP, [hl] ; is the enemy charging up for attack?
jr nz, EnemyCanExecuteChargingMove ; if so, jump
2014-05-22 22:13:20 +00:00
call GetCurrentMove
2016-06-12 00:24:04 +00:00
CheckIfEnemyNeedsToChargeUp:
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
cp CHARGE_EFFECT
2014-08-09 05:39:13 +00:00
jp z, JumpMoveEffect
2014-05-22 22:13:20 +00:00
cp FLY_EFFECT
2014-08-09 05:39:13 +00:00
jp z, JumpMoveEffect
jr EnemyCanExecuteMove
2016-06-12 00:24:04 +00:00
EnemyCanExecuteChargingMove:
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res CHARGING_UP, [hl] ; no longer charging up for attack
res INVULNERABLE, [hl] ; no longer invulnerable to typical attacks
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
ld [wd0b5], a
ld a, BANK(MoveNames)
ld [wPredefBank], a
2014-05-22 22:13:20 +00:00
ld a, MOVE_NAME
2015-02-08 09:44:41 +00:00
ld [wNameListType], a
2014-05-22 22:13:20 +00:00
call GetName
ld de, wcd6d
2014-05-22 22:13:20 +00:00
call CopyStringToCF4B
2016-06-12 00:24:04 +00:00
EnemyCanExecuteMove:
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 18:40:22 +00:00
ld [wMonIsDisobedient], a
2014-05-22 22:13:20 +00:00
call PrintMonName1Text
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2015-01-20 19:21:16 +00:00
ld hl, ResidualEffects1
2014-05-22 22:13:20 +00:00
ld de, $1
call IsInArray
2014-08-09 05:39:13 +00:00
jp c, JumpMoveEffect
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2015-01-20 19:21:16 +00:00
ld hl, SpecialEffectsCont
2014-05-22 22:13:20 +00:00
ld de, $1
call IsInArray
2014-08-09 05:39:13 +00:00
call c, JumpMoveEffect
2016-06-12 00:24:04 +00:00
EnemyCalcMoveDamage:
2014-08-09 05:39:13 +00:00
call SwapPlayerAndEnemyLevels
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2015-01-20 19:21:16 +00:00
ld hl, SetDamageEffects
2014-05-22 22:13:20 +00:00
ld de, $1
call IsInArray
jp c, EnemyMoveHitTest
2014-05-22 22:13:20 +00:00
call CriticalHitTest
call HandleCounterMove
jr z, handleIfEnemyMoveMissed
2014-08-09 05:39:13 +00:00
call SwapPlayerAndEnemyLevels
call GetDamageVarsForEnemyAttack
call SwapPlayerAndEnemyLevels
call CalculateDamage
jp z, EnemyCheckIfFlyOrChargeEffect
2014-05-22 22:13:20 +00:00
call AdjustDamageForMoveType
2014-08-09 05:39:13 +00:00
call RandomizeDamage
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
EnemyMoveHitTest:
2014-05-22 22:13:20 +00:00
call MoveHitTest
2016-06-12 00:24:04 +00:00
handleIfEnemyMoveMissed:
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
2016-06-12 04:30:05 +00:00
jr z, .moveDidNotMiss
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
cp EXPLODE_EFFECT
2016-06-12 04:30:05 +00:00
jr z, handleExplosionMiss
jr EnemyCheckIfFlyOrChargeEffect
2016-06-12 04:30:05 +00:00
.moveDidNotMiss
2014-08-09 05:39:13 +00:00
call SwapPlayerAndEnemyLevels
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
GetEnemyAnimationType:
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
and a
ld a, $1
jr z, playEnemyMoveAnimation
2014-05-22 22:13:20 +00:00
ld a, $2
jr playEnemyMoveAnimation
2016-06-12 04:30:05 +00:00
handleExplosionMiss:
2014-08-09 05:39:13 +00:00
call SwapPlayerAndEnemyLevels
2014-05-22 22:13:20 +00:00
xor a
2016-06-12 00:24:04 +00:00
playEnemyMoveAnimation:
2014-05-22 22:13:20 +00:00
push af
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus2]
2017-12-29 23:59:48 +00:00
bit HAS_SUBSTITUTE_UP, a ; does mon have a substitute?
2015-07-12 22:51:04 +00:00
ld hl, HideSubstituteShowMonAnim
ld b, BANK(HideSubstituteShowMonAnim)
2014-05-22 22:13:20 +00:00
call nz, Bankswitch
pop af
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
2015-01-20 19:21:16 +00:00
call HandleExplodingAnimation
2014-08-09 05:39:13 +00:00
call DrawEnemyHUDAndHPBar
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus2]
2017-12-29 23:59:48 +00:00
bit HAS_SUBSTITUTE_UP, a ; does mon have a substitute?
2015-07-12 22:51:04 +00:00
ld hl, ReshowSubstituteAnim
ld b, BANK(ReshowSubstituteAnim)
2014-05-22 22:13:20 +00:00
call nz, Bankswitch ; slide the substitute's sprite out
jr EnemyCheckIfMirrorMoveEffect
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
EnemyCheckIfFlyOrChargeEffect:
2014-08-09 05:39:13 +00:00
call SwapPlayerAndEnemyLevels
ld c, 30
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
cp FLY_EFFECT
jr z, .playAnim
2014-05-22 22:13:20 +00:00
cp CHARGE_EFFECT
jr z, .playAnim
jr EnemyCheckIfMirrorMoveEffect
.playAnim
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
ld a, STATUS_AFFECTED_ANIM
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
2016-06-12 00:24:04 +00:00
EnemyCheckIfMirrorMoveEffect:
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
cp MIRROR_MOVE_EFFECT
jr nz, .notMirrorMoveEffect
call MirrorMoveCopyMove
jp z, ExecuteEnemyMoveDone
jp CheckIfEnemyNeedsToChargeUp
2014-05-22 22:13:20 +00:00
.notMirrorMoveEffect
cp METRONOME_EFFECT
jr nz, .notMetronomeEffect
call MetronomePickMove
jp CheckIfEnemyNeedsToChargeUp
2014-05-22 22:13:20 +00:00
.notMetronomeEffect
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2015-01-20 19:21:16 +00:00
ld hl, ResidualEffects2
2014-05-22 22:13:20 +00:00
ld de, $1
call IsInArray
2014-08-09 05:39:13 +00:00
jp c, JumpMoveEffect
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
2016-06-12 04:30:05 +00:00
jr z, .moveDidNotMiss
2014-05-22 22:13:20 +00:00
call PrintMoveFailureText
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
cp EXPLODE_EFFECT
2016-06-12 04:30:05 +00:00
jr z, .handleExplosionMiss
jp ExecuteEnemyMoveDone
2016-06-12 04:30:05 +00:00
.moveDidNotMiss
2014-05-22 22:13:20 +00:00
call ApplyAttackToPlayerPokemon
2014-08-09 05:39:13 +00:00
call PrintCriticalOHKOText
2014-05-22 22:13:20 +00:00
callab DisplayEffectiveness
2014-08-09 05:39:13 +00:00
ld a, 1
2015-03-31 18:28:42 +00:00
ld [wMoveDidntMiss], a
2016-06-12 04:30:05 +00:00
.handleExplosionMiss
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2015-01-20 19:21:16 +00:00
ld hl, AlwaysHappenSideEffects
2014-05-22 22:13:20 +00:00
ld de, $1
call IsInArray
2014-08-09 05:39:13 +00:00
call c, JumpMoveEffect
ld hl, wBattleMonHP
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, [hl]
or b
ret z
call HandleBuildingRage
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
bit ATTACKING_MULTIPLE_TIMES, [hl] ; is mon hitting multiple times? (example: double kick)
2016-06-12 04:30:05 +00:00
jr z, .notMultiHitMove
2014-05-22 22:13:20 +00:00
push hl
2014-08-09 05:39:13 +00:00
ld hl, wEnemyNumAttacksLeft
2014-05-22 22:13:20 +00:00
dec [hl]
pop hl
jp nz, GetEnemyAnimationType
2017-12-29 23:59:48 +00:00
res ATTACKING_MULTIPLE_TIMES, [hl] ; mon is no longer hitting multiple times
2014-08-09 05:39:13 +00:00
ld hl, HitXTimesText
2014-05-22 22:13:20 +00:00
call PrintText
xor a
2015-02-07 10:43:08 +00:00
ld [wEnemyNumHits], a
2016-06-12 04:30:05 +00:00
.notMultiHitMove
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
and a
jr z, ExecuteEnemyMoveDone
2015-01-20 19:21:16 +00:00
ld hl, SpecialEffects
2014-05-22 22:13:20 +00:00
ld de, $1
call IsInArray
2014-08-09 05:39:13 +00:00
call nc, JumpMoveEffect
jr ExecuteEnemyMoveDone
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
HitXTimesText:
2014-05-22 22:13:20 +00:00
TX_FAR _HitXTimesText
db "@"
2016-06-12 00:24:04 +00:00
ExecuteEnemyMoveDone:
2014-05-22 22:13:20 +00:00
ld b, $1
ret
2014-08-09 05:39:13 +00:00
; checks for various status conditions affecting the enemy mon
; stores whether the mon cannot use a move this turn in Z flag
2016-06-12 00:24:04 +00:00
CheckEnemyStatusConditions:
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonStatus
2014-05-22 22:13:20 +00:00
ld a, [hl]
2014-08-09 05:39:13 +00:00
and SLP ; sleep mask
jr z, .checkIfFrozen
dec a ; decrement number of turns left
ld [wEnemyMonStatus], a
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .wokeUp ; if the number of turns hit 0, wake up
2014-05-22 22:13:20 +00:00
ld hl, FastAsleepText
call PrintText
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
ld a, SLP_ANIM
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
jr .sleepDone
2014-08-09 05:39:13 +00:00
.wokeUp
2014-05-22 22:13:20 +00:00
ld hl, WokeUpText
call PrintText
.sleepDone
2014-05-22 22:13:20 +00:00
xor a
ld [wEnemyUsedMove], a
ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfFrozen
bit FRZ, [hl]
jr z, .checkIfTrapped
2014-05-22 22:13:20 +00:00
ld hl, IsFrozenText
call PrintText
xor a
ld [wEnemyUsedMove], a
ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfTrapped
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus1]
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, a ; is the player using a multi-turn attack like warp
2014-08-09 05:39:13 +00:00
jp z, .checkIfFlinched
2014-05-22 22:13:20 +00:00
ld hl, CantMoveText
call PrintText
ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfFlinched
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
bit FLINCHED, [hl] ; check if enemy mon flinched
2014-08-09 05:39:13 +00:00
jp z, .checkIfMustRecharge
2017-12-29 23:59:48 +00:00
res FLINCHED, [hl]
2014-05-22 22:13:20 +00:00
ld hl, FlinchedText
call PrintText
ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfMustRecharge
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus2
2017-12-29 23:59:48 +00:00
bit NEEDS_TO_RECHARGE, [hl] ; check if enemy mon has to recharge after using a move
2014-08-09 05:39:13 +00:00
jr z, .checkIfAnyMoveDisabled
2017-12-29 23:59:48 +00:00
res NEEDS_TO_RECHARGE, [hl]
2014-05-22 22:13:20 +00:00
ld hl, MustRechargeText
call PrintText
ld hl, ExecuteEnemyMoveDone ; enemy can't move this turn
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfAnyMoveDisabled
2015-08-31 02:38:41 +00:00
ld hl, wEnemyDisabledMove
2014-05-22 22:13:20 +00:00
ld a, [hl]
and a
2014-08-09 05:39:13 +00:00
jr z, .checkIfConfused
dec a ; decrement disable counter
2014-05-22 22:13:20 +00:00
ld [hl], a
and $f ; did disable counter hit 0?
2014-08-09 05:39:13 +00:00
jr nz, .checkIfConfused
2014-05-22 22:13:20 +00:00
ld [hl], a
ld [wEnemyDisabledMoveNumber], a
2014-05-22 22:13:20 +00:00
ld hl, DisabledNoMoreText
call PrintText
2014-08-09 05:39:13 +00:00
.checkIfConfused
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus1]
2014-08-09 05:39:13 +00:00
add a ; check if enemy mon is confused
jp nc, .checkIfTriedToUseDisabledMove
2015-08-31 02:38:41 +00:00
ld hl, wEnemyConfusedCounter
2014-05-22 22:13:20 +00:00
dec [hl]
2014-08-09 05:39:13 +00:00
jr nz, .isConfused
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res CONFUSED, [hl] ; if confused counter hit 0, reset confusion status
2014-05-22 22:13:20 +00:00
ld hl, ConfusedNoMoreText
call PrintText
2014-08-09 05:39:13 +00:00
jp .checkIfTriedToUseDisabledMove
.isConfused
2014-05-22 22:13:20 +00:00
ld hl, IsConfusedText
call PrintText
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
ld a, CONF_ANIM
2014-05-22 22:13:20 +00:00
call PlayMoveAnimation
call BattleRandom
2014-05-22 22:13:20 +00:00
cp $80
2014-08-09 05:39:13 +00:00
jr c, .checkIfTriedToUseDisabledMove
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-05-22 22:13:20 +00:00
ld a, [hl]
2017-12-29 23:59:48 +00:00
and 1 << CONFUSED ; if mon hurts itself, clear every other status from wEnemyBattleStatus1
2014-05-22 22:13:20 +00:00
ld [hl], a
ld hl, HurtItselfText
call PrintText
ld hl, wBattleMonDefense
2014-05-22 22:13:20 +00:00
ld a, [hli]
push af
ld a, [hld]
push af
2014-08-09 05:39:13 +00:00
ld a, [wEnemyMonDefense]
2014-05-22 22:13:20 +00:00
ld [hli], a
ld a, [wEnemyMonDefense + 1]
2014-05-22 22:13:20 +00:00
ld [hl], a
2015-08-31 02:38:41 +00:00
ld hl, wEnemyMoveEffect
2014-05-22 22:13:20 +00:00
push hl
ld a, [hl]
push af
xor a
ld [hli], a
2014-08-09 05:39:13 +00:00
ld [wCriticalHitOrOHKO], a
ld a, 40
2014-05-22 22:13:20 +00:00
ld [hli], a
xor a
ld [hl], a
2014-08-09 05:39:13 +00:00
call GetDamageVarsForEnemyAttack
call CalculateDamage
2014-05-22 22:13:20 +00:00
pop af
pop hl
ld [hl], a
ld hl, wBattleMonDefense + 1
2014-05-22 22:13:20 +00:00
pop af
ld [hld], a
pop af
ld [hl], a
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
ld a, POUND
call PlayMoveAnimation
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
2014-05-22 22:13:20 +00:00
call ApplyDamageToEnemyPokemon
2014-08-09 05:39:13 +00:00
jr .monHurtItselfOrFullyParalysed
.checkIfTriedToUseDisabledMove
; prevents a disabled move that was selected before being disabled from being used
ld a, [wEnemyDisabledMoveNumber]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .checkIfParalysed
ld hl, wEnemySelectedMove
2014-05-22 22:13:20 +00:00
cp [hl]
2014-08-09 05:39:13 +00:00
jr nz, .checkIfParalysed
2014-05-22 22:13:20 +00:00
call PrintMoveIsDisabledText
ld hl, ExecuteEnemyMoveDone ; if a disabled move was somehow selected, player can't move this turn
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfParalysed
ld hl, wEnemyMonStatus
bit PAR, [hl]
jr z, .checkIfUsingBide
call BattleRandom
cp $3f ; 25% to be fully paralysed
2014-08-09 05:39:13 +00:00
jr nc, .checkIfUsingBide
2014-05-22 22:13:20 +00:00
ld hl, FullyParalyzedText
call PrintText
2014-08-09 05:39:13 +00:00
.monHurtItselfOrFullyParalysed
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-05-22 22:13:20 +00:00
ld a, [hl]
2015-06-11 22:41:33 +00:00
; clear bide, thrashing about, charging up, and multi-turn moves such as warp
2017-12-29 23:59:48 +00:00
and $ff ^ ((1 << STORING_ENERGY) | (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) | (1 << USING_TRAPPING_MOVE))
2014-05-22 22:13:20 +00:00
ld [hl], a
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
cp FLY_EFFECT
2014-08-09 05:39:13 +00:00
jr z, .flyOrChargeEffect
2014-05-22 22:13:20 +00:00
cp CHARGE_EFFECT
2014-08-09 05:39:13 +00:00
jr z, .flyOrChargeEffect
jr .notFlyOrChargeEffect
.flyOrChargeEffect
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-05-22 22:13:20 +00:00
ld a, STATUS_AFFECTED_ANIM
call PlayMoveAnimation
2014-08-09 05:39:13 +00:00
.notFlyOrChargeEffect
ld hl, ExecuteEnemyMoveDone
jp .enemyReturnToHL ; if using a two-turn move, enemy needs to recharge the first turn
2014-08-09 05:39:13 +00:00
.checkIfUsingBide
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
bit STORING_ENERGY, [hl] ; is mon using bide?
2014-08-09 05:39:13 +00:00
jr z, .checkIfThrashingAbout
2014-05-22 22:13:20 +00:00
xor a
2015-08-31 02:38:41 +00:00
ld [wEnemyMoveNum], a
ld hl, wDamage
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, a
ld c, [hl]
2015-02-07 10:43:08 +00:00
ld hl, wEnemyBideAccumulatedDamage + 1
2014-05-22 22:13:20 +00:00
ld a, [hl]
add c ; accumulate damage taken
2014-05-22 22:13:20 +00:00
ld [hld], a
ld a, [hl]
adc b
ld [hl], a
2014-08-09 05:39:13 +00:00
ld hl, wEnemyNumAttacksLeft
dec [hl] ; did Bide counter hit 0?
2014-08-09 05:39:13 +00:00
jr z, .unleashEnergy
ld hl, ExecuteEnemyMoveDone
jp .enemyReturnToHL ; unless mon unleashes energy, can't move this turn
2014-08-09 05:39:13 +00:00
.unleashEnergy
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res STORING_ENERGY, [hl] ; not using bide any more
2014-05-22 22:13:20 +00:00
ld hl, UnleashedEnergyText
call PrintText
ld a, $1
2015-08-31 02:38:41 +00:00
ld [wEnemyMovePower], a
2015-02-07 10:43:08 +00:00
ld hl, wEnemyBideAccumulatedDamage + 1
2014-05-22 22:13:20 +00:00
ld a, [hld]
add a
ld b, a
2015-08-31 02:38:41 +00:00
ld [wDamage + 1], a
2014-05-22 22:13:20 +00:00
ld a, [hl]
rl a ; double the damage
2015-08-31 02:38:41 +00:00
ld [wDamage], a
2014-05-22 22:13:20 +00:00
or b
jr nz, .next
2014-05-22 22:13:20 +00:00
ld a, $1
2015-08-31 02:38:41 +00:00
ld [wMoveMissed], a
.next
2014-05-22 22:13:20 +00:00
xor a
ld [hli], a
ld [hl], a
ld a, BIDE
2015-08-31 02:38:41 +00:00
ld [wEnemyMoveNum], a
2014-08-09 05:39:13 +00:00
call SwapPlayerAndEnemyLevels
ld hl, handleIfEnemyMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfThrashingAbout
2017-12-29 23:59:48 +00:00
bit THRASHING_ABOUT, [hl] ; is mon using thrash or petal dance?
2014-08-09 05:39:13 +00:00
jr z, .checkIfUsingMultiturnMove
2014-05-22 22:13:20 +00:00
ld a, THRASH
2015-08-31 02:38:41 +00:00
ld [wEnemyMoveNum], a
2014-05-22 22:13:20 +00:00
ld hl, ThrashingAboutText
call PrintText
2014-08-09 05:39:13 +00:00
ld hl, wEnemyNumAttacksLeft
dec [hl] ; did Thrashing About counter hit 0?
ld hl, EnemyCalcMoveDamage ; skip DecrementPP
jp nz, .enemyReturnToHL
2014-05-22 22:13:20 +00:00
push hl
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2017-12-29 23:59:48 +00:00
res THRASHING_ABOUT, [hl] ; mon is no longer using thrash or petal dance
set CONFUSED, [hl] ; mon is now confused
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
inc a
inc a ; confused for 2-5 turns
2015-08-31 02:38:41 +00:00
ld [wEnemyConfusedCounter], a
pop hl ; skip DecrementPP
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfUsingMultiturnMove
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, [hl] ; is mon using multi-turn move?
2014-08-09 05:39:13 +00:00
jp z, .checkIfUsingRage
2014-05-22 22:13:20 +00:00
ld hl, AttackContinuesText
call PrintText
2014-08-09 05:39:13 +00:00
ld hl, wEnemyNumAttacksLeft
dec [hl] ; did multi-turn move end?
2015-06-11 22:41:33 +00:00
ld hl, GetEnemyAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit),
; DecrementPP and MoveHitTest
jp nz, .enemyReturnToHL
jp .enemyReturnToHL
2014-08-09 05:39:13 +00:00
.checkIfUsingRage
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus2]
2017-12-29 23:59:48 +00:00
bit USING_RAGE, a ; is mon using rage?
jp z, .checkEnemyStatusConditionsDone ; if we made it this far, mon can move normally this turn
2014-05-22 22:13:20 +00:00
ld a, RAGE
ld [wd11e], a
2014-05-22 22:13:20 +00:00
call GetMoveName
call CopyStringToCF4B
xor a
2015-08-31 02:38:41 +00:00
ld [wEnemyMoveEffect], a
ld hl, EnemyCanExecuteMove
jp .enemyReturnToHL
.enemyReturnToHL
2014-08-09 05:39:13 +00:00
xor a ; set Z flag
2014-05-22 22:13:20 +00:00
ret
.checkEnemyStatusConditionsDone
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
and a ; clear Z flag
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
GetCurrentMove:
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jp z, .player
2015-08-31 02:38:41 +00:00
ld de, wEnemyMoveNum
2014-08-09 05:39:13 +00:00
ld a, [wEnemySelectedMove]
2014-05-22 22:13:20 +00:00
jr .selected
.player
2015-08-31 02:38:41 +00:00
ld de, wPlayerMoveNum
ld a, [wFlags_D733]
2015-08-14 02:13:47 +00:00
bit BIT_TEST_BATTLE, a
ld a, [wTestBattlePlayerSelectedMove]
2014-05-22 22:13:20 +00:00
jr nz, .selected
2014-08-09 05:39:13 +00:00
ld a, [wPlayerSelectedMove]
2014-05-22 22:13:20 +00:00
.selected
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
ld hl, Moves
2015-08-10 04:56:20 +00:00
ld bc, MoveEnd - Moves
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, BANK(Moves)
call FarCopyData
ld a, BANK(MoveNames)
ld [wPredefBank], a
ld a, MOVE_NAME
2015-02-08 09:44:41 +00:00
ld [wNameListType], a
2014-05-22 22:13:20 +00:00
call GetName
ld de, wcd6d
2014-05-22 22:13:20 +00:00
jp CopyStringToCF4B
2016-06-12 00:24:04 +00:00
LoadEnemyMonData:
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-08-09 05:39:13 +00:00
jp z, LoadEnemyMonFromParty
ld a, [wEnemyMonSpecies2]
ld [wEnemyMonSpecies], a
ld [wd0b5], a
2014-05-22 22:13:20 +00:00
call GetMonHeader
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus3]
2017-12-29 23:59:48 +00:00
bit TRANSFORMED, a ; is enemy mon transformed?
2015-08-14 07:36:06 +00:00
ld hl, wTransformedEnemyMonOriginalDVs ; original DVs before transforming
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, [hl]
2014-08-09 05:39:13 +00:00
jr nz, .storeDVs
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-08-09 05:39:13 +00:00
cp $2 ; is it a trainer battle?
; fixed DVs for trainer mon
2014-05-22 22:13:20 +00:00
ld a, $98
ld b, $88
2014-08-09 05:39:13 +00:00
jr z, .storeDVs
; random DVs for wild mon
call BattleRandom
2014-05-22 22:13:20 +00:00
ld b, a
call BattleRandom
2014-08-09 05:39:13 +00:00
.storeDVs
ld hl, wEnemyMonDVs
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hl], b
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonLevel
2015-08-31 02:38:41 +00:00
ld a, [wCurEnemyLVL]
2014-05-22 22:13:20 +00:00
ld [de], a
inc de
ld b, $0
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonHP
2014-05-22 22:13:20 +00:00
push hl
call CalcStats
pop hl
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-08-09 05:39:13 +00:00
cp $2 ; is it a trainer battle?
jr z, .copyHPAndStatusFromPartyData
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus3]
2017-12-29 23:59:48 +00:00
bit TRANSFORMED, a ; is enemy mon transformed?
2014-08-09 05:39:13 +00:00
jr nz, .copyTypes ; if transformed, jump
; if it's a wild mon and not transformed, init the current HP to max HP and the status to 0
ld a, [wEnemyMonMaxHP]
2014-05-22 22:13:20 +00:00
ld [hli], a
ld a, [wEnemyMonMaxHP+1]
2014-05-22 22:13:20 +00:00
ld [hli], a
xor a
inc hl
2014-08-09 05:39:13 +00:00
ld [hl], a ; init status to 0
jr .copyTypes
; if it's a trainer mon, copy the HP and status from the enemy party data
.copyHPAndStatusFromPartyData
ld hl, wEnemyMon1HP
ld a, [wWhichPokemon]
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld a, [hli]
2014-08-09 05:39:13 +00:00
ld [wEnemyMonHP], a
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [wEnemyMonHP + 1], a
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld [wEnemyMonPartyPos], a
2014-05-22 22:13:20 +00:00
inc hl
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [wEnemyMonStatus], a
jr .copyTypes
.copyTypes
2015-08-31 02:38:41 +00:00
ld hl, wMonHTypes
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonType
2014-05-22 22:13:20 +00:00
ld a, [hli] ; copy type 1
ld [de], a
inc de
ld a, [hli] ; copy type 2
ld [de], a
inc de
ld a, [hli] ; copy catch rate
ld [de], a
inc de
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-08-09 05:39:13 +00:00
cp $2 ; is it a trainer battle?
jr nz, .copyStandardMoves
; if it's a trainer battle, copy moves from enemy party data
ld hl, wEnemyMon1Moves
2014-08-09 05:39:13 +00:00
ld a, [wWhichPokemon]
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
ld bc, NUM_MOVES
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
jr .loadMovePPs
.copyStandardMoves
; for a wild mon, first copy default moves from the mon header
2015-08-31 02:38:41 +00:00
ld hl, wMonHMoves
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hli]
ld [de], a
inc de
ld a, [hl]
ld [de], a
dec de
dec de
dec de
xor a
2015-07-19 03:49:52 +00:00
ld [wLearningMovesFromDayCare], a
2014-08-09 05:39:13 +00:00
predef WriteMonMoves ; get moves based on current level
.loadMovePPs
ld hl, wEnemyMonMoves
2015-07-20 00:52:26 +00:00
ld de, wEnemyMonPP - 1
predef LoadMovePPs
2015-08-31 02:38:41 +00:00
ld hl, wMonHBaseStats
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonBaseStats
ld b, NUM_STATS
2014-08-09 05:39:13 +00:00
.copyBaseStatsLoop
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [de], a
inc de
dec b
2014-08-09 05:39:13 +00:00
jr nz, .copyBaseStatsLoop
2015-08-31 02:38:41 +00:00
ld hl, wMonHCatchRate
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld [de], a
inc de
ld a, [hl] ; base exp
ld [de], a
ld a, [wEnemyMonSpecies2]
ld [wd11e], a
2014-05-22 22:13:20 +00:00
call GetMonName
ld hl, wcd6d
ld de, wEnemyMonNick
ld bc, NAME_LENGTH
2014-05-22 22:13:20 +00:00
call CopyData
ld a, [wEnemyMonSpecies2]
ld [wd11e], a
predef IndexToPokedex
ld a, [wd11e]
2014-05-22 22:13:20 +00:00
dec a
ld c, a
2015-07-20 03:45:34 +00:00
ld b, FLAG_SET
2014-08-09 05:39:13 +00:00
ld hl, wPokedexSeen
predef FlagActionPredef ; mark this mon as seen in the pokedex
ld hl, wEnemyMonLevel
ld de, wEnemyMonUnmodifiedLevel
ld bc, 1 + NUM_STATS * 2
2014-05-22 22:13:20 +00:00
call CopyData
2014-08-09 05:39:13 +00:00
ld a, $7 ; default stat mod
ld b, NUM_STAT_MODS ; number of stat mods
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonStatMods
.statModLoop
2014-05-22 22:13:20 +00:00
ld [hli], a
dec b
2014-08-09 05:39:13 +00:00
jr nz, .statModLoop
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; calls BattleTransition to show the battle transition animation and initializes some battle variables
2016-06-12 00:24:04 +00:00
DoBattleTransitionAndInitBattleVariables:
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-08-09 05:39:13 +00:00
jr nz, .next
; link battle
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [wMenuJoypadPollCount], a
callab DisplayLinkBattleVersusTextBox
2014-05-22 22:13:20 +00:00
ld a, $1
2014-09-13 07:50:56 +00:00
ld [wUpdateSpritesEnabled], a
2014-05-22 22:13:20 +00:00
call ClearScreen
2014-08-09 05:39:13 +00:00
.next
2014-05-22 22:13:20 +00:00
call DelayFrame
predef BattleTransition
2014-08-09 05:39:13 +00:00
callab LoadHudAndHpBarAndStatusTilePatterns
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-05-22 22:13:20 +00:00
ld a, $ff
2014-09-13 07:50:56 +00:00
ld [wUpdateSpritesEnabled], a
2014-05-23 22:34:35 +00:00
call ClearSprites
2014-05-22 22:13:20 +00:00
call ClearScreen
xor a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-09-23 22:02:03 +00:00
ld [hWY], a
2014-08-09 05:39:13 +00:00
ld [rWY], a
2014-09-14 18:29:18 +00:00
ld [hTilesetType], a
2015-02-08 09:44:41 +00:00
ld hl, wPlayerStatsToDouble
2014-05-22 22:13:20 +00:00
ld [hli], a
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
2015-08-31 02:38:41 +00:00
ld [wPlayerDisabledMove], a
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; swaps the level values of the BattleMon and EnemyMon structs
2016-06-12 00:24:04 +00:00
SwapPlayerAndEnemyLevels:
2014-05-22 22:13:20 +00:00
push bc
2014-08-09 05:39:13 +00:00
ld a, [wBattleMonLevel]
2014-05-22 22:13:20 +00:00
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wEnemyMonLevel]
ld [wBattleMonLevel], a
2014-05-22 22:13:20 +00:00
ld a, b
2014-08-09 05:39:13 +00:00
ld [wEnemyMonLevel], a
2014-05-22 22:13:20 +00:00
pop bc
ret
2014-08-09 05:39:13 +00:00
; loads either red back pic or old man back pic
; also writes OAM data and loads tile patterns for the Red or Old Man back sprite's head
; (for use when scrolling the player sprite and enemy's silhouettes on screen)
2016-06-12 00:24:04 +00:00
LoadPlayerBackPic:
2015-08-31 02:38:41 +00:00
ld a, [wBattleType]
2014-08-09 05:39:13 +00:00
dec a ; is it the old man tutorial?
ld de, RedPicBack
jr nz, .next
ld de, OldManPic
.next
2014-05-22 22:13:20 +00:00
ld a, BANK(RedPicBack)
call UncompressSpriteFromDE
predef ScaleSpriteByTwo
2014-05-22 22:13:20 +00:00
ld hl, wOAMBuffer
xor a
2015-07-18 15:17:29 +00:00
ld [hOAMTile], a ; initial tile number
2014-08-09 05:39:13 +00:00
ld b, $7 ; 7 columns
ld e, $a0 ; X for the left-most column
.loop ; each loop iteration writes 3 OAM entries in a vertical column
ld c, $3 ; 3 tiles per column
ld d, $38 ; Y for the top of each column
.innerLoop ; each loop iteration writes 1 OAM entry in the column
ld [hl], d ; OAM Y
2014-05-22 22:13:20 +00:00
inc hl
2014-08-09 05:39:13 +00:00
ld [hl], e ; OAM X
ld a, $8 ; height of tile
add d ; increase Y by height of tile
2014-05-22 22:13:20 +00:00
ld d, a
inc hl
2015-07-18 15:17:29 +00:00
ld a, [hOAMTile]
2014-08-09 05:39:13 +00:00
ld [hli], a ; OAM tile number
inc a ; increment tile number
2015-07-18 15:17:29 +00:00
ld [hOAMTile], a
2014-05-22 22:13:20 +00:00
inc hl
dec c
2014-08-09 05:39:13 +00:00
jr nz, .innerLoop
2015-07-18 15:17:29 +00:00
ld a, [hOAMTile]
2014-08-09 05:39:13 +00:00
add $4 ; increase tile number by 4
2015-07-18 15:17:29 +00:00
ld [hOAMTile], a
2014-08-09 05:39:13 +00:00
ld a, $8 ; width of tile
add e ; increase X by width of tile
2014-05-22 22:13:20 +00:00
ld e, a
dec b
2014-08-09 05:39:13 +00:00
jr nz, .loop
2014-05-29 08:31:46 +00:00
ld de, vBackPic
2014-05-22 22:13:20 +00:00
call InterlaceMergeSpriteBuffers
ld a, $a
ld [$0], a
xor a
ld [$4000], a
2014-05-29 08:31:46 +00:00
ld hl, vSprites
2015-08-31 03:15:32 +00:00
ld de, sSpriteBuffer1
2014-05-22 22:13:20 +00:00
ld a, [H_LOADEDROMBANK]
ld b, a
2014-05-29 08:31:46 +00:00
ld c, 7 * 7
2014-05-22 22:13:20 +00:00
call CopyVideoData
xor a
ld [$0], a
ld a, $31
2015-07-24 03:48:35 +00:00
ld [hStartTileID], a
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
predef_jump CopyUncompressedPicToTilemap
2014-05-22 22:13:20 +00:00
2015-02-08 09:44:41 +00:00
; does nothing since no stats are ever selected (barring glitches)
2016-06-12 00:24:04 +00:00
DoubleOrHalveSelectedStats:
2015-02-08 09:44:41 +00:00
callab DoubleSelectedStats
2015-07-19 18:56:13 +00:00
jpab HalveSelectedStats
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ScrollTrainerPicAfterBattle:
2015-07-19 18:56:13 +00:00
jpab _ScrollTrainerPicAfterBattle
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ApplyBurnAndParalysisPenaltiesToPlayer:
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
jr ApplyBurnAndParalysisPenalties
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ApplyBurnAndParalysisPenaltiesToEnemy:
2014-05-22 22:13:20 +00:00
xor a
2016-06-12 00:24:04 +00:00
ApplyBurnAndParalysisPenalties:
2014-08-09 05:39:13 +00:00
ld [H_WHOSETURN], a
call QuarterSpeedDueToParalysis
jp HalveAttackDueToBurn
2016-06-12 00:24:04 +00:00
QuarterSpeedDueToParalysis:
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .playerTurn
.enemyTurn ; quarter the player's speed
ld a, [wBattleMonStatus]
and 1 << PAR
ret z ; return if player not paralysed
ld hl, wBattleMonSpeed + 1
2014-05-22 22:13:20 +00:00
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
srl a
rr b
ld [hli], a
or b
2014-08-09 05:39:13 +00:00
jr nz, .storePlayerSpeed
ld b, 1 ; give the player a minimum of at least one speed point
.storePlayerSpeed
2014-05-22 22:13:20 +00:00
ld [hl], b
ret
2014-08-09 05:39:13 +00:00
.playerTurn ; quarter the enemy's speed
ld a, [wEnemyMonStatus]
and 1 << PAR
ret z ; return if enemy not paralysed
ld hl, wEnemyMonSpeed + 1
2014-05-22 22:13:20 +00:00
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
srl a
rr b
ld [hli], a
or b
2014-08-09 05:39:13 +00:00
jr nz, .storeEnemySpeed
ld b, 1 ; give the enemy a minimum of at least one speed point
.storeEnemySpeed
2014-05-22 22:13:20 +00:00
ld [hl], b
ret
2016-06-12 00:24:04 +00:00
HalveAttackDueToBurn:
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
jr z, .playerTurn
.enemyTurn ; halve the player's attack
ld a, [wBattleMonStatus]
and 1 << BRN
ret z ; return if player not burnt
ld hl, wBattleMonAttack + 1
2014-05-22 22:13:20 +00:00
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
ld [hli], a
or b
2014-08-09 05:39:13 +00:00
jr nz, .storePlayerAttack
ld b, 1 ; give the player a minimum of at least one attack point
.storePlayerAttack
2014-05-22 22:13:20 +00:00
ld [hl], b
ret
2014-08-09 05:39:13 +00:00
.playerTurn ; halve the enemy's attack
ld a, [wEnemyMonStatus]
and 1 << BRN
ret z ; return if enemy not burnt
ld hl, wEnemyMonAttack + 1
2014-05-22 22:13:20 +00:00
ld a, [hld]
ld b, a
ld a, [hl]
srl a
rr b
ld [hli], a
or b
2014-08-09 05:39:13 +00:00
jr nz, .storeEnemyAttack
ld b, 1 ; give the enemy a minimum of at least one attack point
.storeEnemyAttack
2014-05-22 22:13:20 +00:00
ld [hl], b
ret
2016-06-12 00:24:04 +00:00
CalculateModifiedStats:
2014-08-09 05:39:13 +00:00
ld c, 0
.loop
call CalculateModifiedStat
2014-05-22 22:13:20 +00:00
inc c
ld a, c
cp NUM_STATS - 1
2014-08-09 05:39:13 +00:00
jr nz, .loop
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; calculate modified stat for stat c (0 = attack, 1 = defense, 2 = speed, 3 = special)
2016-06-12 00:24:04 +00:00
CalculateModifiedStat:
2014-05-22 22:13:20 +00:00
push bc
push bc
2015-08-07 12:20:37 +00:00
ld a, [wCalculateWhoseStats]
2014-05-22 22:13:20 +00:00
and a
ld a, c
ld hl, wBattleMonAttack
2014-08-09 05:39:13 +00:00
ld de, wPlayerMonUnmodifiedAttack
2015-08-07 12:20:37 +00:00
ld bc, wPlayerMonStatMods
2014-08-09 05:39:13 +00:00
jr z, .next
ld hl, wEnemyMonAttack
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonUnmodifiedAttack
ld bc, wEnemyMonStatMods
.next
2014-05-22 22:13:20 +00:00
add c
ld c, a
2014-08-09 05:39:13 +00:00
jr nc, .noCarry1
2014-05-22 22:13:20 +00:00
inc b
2014-08-09 05:39:13 +00:00
.noCarry1
2014-05-22 22:13:20 +00:00
ld a, [bc]
pop bc
ld b, a
push bc
sla c
2014-08-09 05:39:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, c
add e
ld e, a
2014-08-09 05:39:13 +00:00
jr nc, .noCarry2
2014-05-22 22:13:20 +00:00
inc d
2014-08-09 05:39:13 +00:00
.noCarry2
2014-05-22 22:13:20 +00:00
pop bc
push hl
2014-08-09 05:39:13 +00:00
ld hl, StatModifierRatios
2014-05-22 22:13:20 +00:00
dec b
sla b
ld c, b
2014-08-09 05:39:13 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
add hl, bc
xor a
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND], a
2014-05-22 22:13:20 +00:00
ld a, [de]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
ld a, [hli]
2014-08-09 05:39:13 +00:00
ld [H_MULTIPLIER], a
2014-05-22 22:13:20 +00:00
call Multiply
ld a, [hl]
2014-08-09 05:39:13 +00:00
ld [H_DIVISOR], a
2014-05-22 22:13:20 +00:00
ld b, $4
call Divide
pop hl
2014-08-09 05:39:13 +00:00
ld a, [H_DIVIDEND + 3]
sub 999 % $100
ld a, [H_DIVIDEND + 2]
sbc 999 / $100
jp c, .storeNewStatValue
; cap the stat at 999
ld a, 999 / $100
ld [H_DIVIDEND + 2], a
ld a, 999 % $100
ld [H_DIVIDEND + 3], a
.storeNewStatValue
ld a, [H_DIVIDEND + 2]
2014-05-22 22:13:20 +00:00
ld [hli], a
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [H_DIVIDEND + 3]
2014-05-22 22:13:20 +00:00
ld [hl], a
or b
2014-08-09 05:39:13 +00:00
jr nz, .done
inc [hl] ; if the stat is 0, bump it up to 1
.done
2014-05-22 22:13:20 +00:00
pop bc
ret
2016-06-12 00:24:04 +00:00
ApplyBadgeStatBoosts:
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2014-08-09 05:39:13 +00:00
ret z ; return if link battle
2015-08-31 02:38:41 +00:00
ld a, [wObtainedBadges]
2014-05-22 22:13:20 +00:00
ld b, a
ld hl, wBattleMonAttack
2014-05-22 22:13:20 +00:00
ld c, $4
2014-08-09 05:39:13 +00:00
; the boost is applied for badges whose bit position is even
; the order of boosts matches the order they are laid out in RAM
; Boulder (bit 0) - attack
; Thunder (bit 2) - defense
; Soul (bit 4) - speed
; Volcano (bit 6) - special
.loop
2014-05-22 22:13:20 +00:00
srl b
2014-08-09 05:39:13 +00:00
call c, .applyBoostToStat
2014-05-22 22:13:20 +00:00
inc hl
inc hl
srl b
dec c
2014-08-09 05:39:13 +00:00
jr nz, .loop
2014-05-22 22:13:20 +00:00
ret
2014-08-09 05:39:13 +00:00
; multiply stat at hl by 1.125
; cap stat at 999
.applyBoostToStat
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld d, a
ld e, [hl]
srl d
rr e
srl d
rr e
srl d
rr e
ld a, [hl]
add e
ld [hld], a
ld a, [hl]
adc d
ld [hli], a
ld a, [hld]
2014-08-09 05:39:13 +00:00
sub 999 % $100
2014-05-22 22:13:20 +00:00
ld a, [hl]
2014-08-09 05:39:13 +00:00
sbc 999 / $100
2014-05-22 22:13:20 +00:00
ret c
2014-08-09 05:39:13 +00:00
ld a, 999 / $100
2014-05-22 22:13:20 +00:00
ld [hli], a
2014-08-09 05:39:13 +00:00
ld a, 999 % $100
2014-05-22 22:13:20 +00:00
ld [hld], a
ret
2016-06-12 00:24:04 +00:00
LoadHudAndHpBarAndStatusTilePatterns:
2014-05-22 22:13:20 +00:00
call LoadHpBarAndStatusTilePatterns
2016-06-12 00:24:04 +00:00
LoadHudTilePatterns:
2014-08-09 05:39:13 +00:00
ld a, [rLCDC]
add a ; is LCD disabled?
jr c, .lcdEnabled
.lcdDisabled
ld hl, BattleHudTiles1
2014-05-29 08:31:46 +00:00
ld de, vChars2 + $6d0
2015-08-10 04:56:20 +00:00
ld bc, BattleHudTiles1End - BattleHudTiles1
2014-05-22 22:13:20 +00:00
ld a, BANK(BattleHudTiles1)
call FarCopyDataDouble
2014-08-09 05:39:13 +00:00
ld hl, BattleHudTiles2
2014-05-29 08:31:46 +00:00
ld de, vChars2 + $730
2015-08-10 04:56:20 +00:00
ld bc, BattleHudTiles3End - BattleHudTiles2
2014-05-22 22:13:20 +00:00
ld a, BANK(BattleHudTiles2)
jp FarCopyDataDouble
2014-08-09 05:39:13 +00:00
.lcdEnabled
ld de, BattleHudTiles1
2014-05-29 08:31:46 +00:00
ld hl, vChars2 + $6d0
2015-08-10 04:56:20 +00:00
lb bc, BANK(BattleHudTiles1), (BattleHudTiles1End - BattleHudTiles1) / $8
2014-05-22 22:13:20 +00:00
call CopyVideoDataDouble
2014-08-09 05:39:13 +00:00
ld de, BattleHudTiles2
2014-05-29 08:31:46 +00:00
ld hl, vChars2 + $730
2015-08-10 04:56:20 +00:00
lb bc, BANK(BattleHudTiles2), (BattleHudTiles3End - BattleHudTiles2) / $8
2014-05-22 22:13:20 +00:00
jp CopyVideoDataDouble
2016-06-12 00:24:04 +00:00
PrintEmptyString:
2014-08-09 05:39:13 +00:00
ld hl, .emptyString
2014-05-22 22:13:20 +00:00
jp PrintText
2014-08-09 05:39:13 +00:00
.emptyString
2014-05-22 22:13:20 +00:00
db "@"
BattleRandom:
; Link battles use a shared PRNG.
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
jp nz, Random
2014-05-22 22:13:20 +00:00
push hl
push bc
2015-02-07 10:43:08 +00:00
ld a, [wLinkBattleRandomNumberListIndex]
2014-05-22 22:13:20 +00:00
ld c, a
ld b, 0
2015-02-07 10:43:08 +00:00
ld hl, wLinkBattleRandomNumberList
2014-05-22 22:13:20 +00:00
add hl, bc
inc a
2015-02-07 10:43:08 +00:00
ld [wLinkBattleRandomNumberListIndex], a
cp 9
2014-05-22 22:13:20 +00:00
ld a, [hl]
pop bc
pop hl
ret c
; if we picked the last seed, we need to recalculate the nine seeds
2014-05-22 22:13:20 +00:00
push hl
push bc
push af
2015-06-11 22:41:33 +00:00
; point to seed 0 so we pick the first number the next time
2014-05-22 22:13:20 +00:00
xor a
2015-02-07 10:43:08 +00:00
ld [wLinkBattleRandomNumberListIndex], a
ld hl, wLinkBattleRandomNumberList
ld b, 9
.loop
2014-05-22 22:13:20 +00:00
ld a, [hl]
ld c, a
2015-06-11 22:41:33 +00:00
; multiply by 5
2014-05-22 22:13:20 +00:00
add a
add a
add c
2015-06-11 22:41:33 +00:00
; add 1
2014-05-22 22:13:20 +00:00
inc a
ld [hli], a
dec b
jr nz, .loop
2014-05-22 22:13:20 +00:00
pop af
pop bc
pop hl
ret
2016-06-12 00:24:04 +00:00
HandleExplodingAnimation:
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld hl, wEnemyMonType1
2015-08-31 02:38:41 +00:00
ld de, wEnemyBattleStatus1
ld a, [wPlayerMoveNum]
2016-06-12 04:30:05 +00:00
jr z, .player
ld hl, wBattleMonType1
2015-08-31 02:38:41 +00:00
ld de, wEnemyBattleStatus1
ld a, [wEnemyMoveNum]
2016-06-12 04:30:05 +00:00
.player
2014-05-22 22:13:20 +00:00
cp SELFDESTRUCT
2016-06-12 04:30:05 +00:00
jr z, .isExplodingMove
2014-05-22 22:13:20 +00:00
cp EXPLOSION
ret nz
2016-06-12 04:30:05 +00:00
.isExplodingMove
2014-05-22 22:13:20 +00:00
ld a, [de]
2017-12-29 23:59:48 +00:00
bit INVULNERABLE, a ; fly/dig
2014-05-22 22:13:20 +00:00
ret nz
ld a, [hli]
cp GHOST
ret z
ld a, [hl]
cp GHOST
ret z
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
ret nz
2015-01-20 19:21:16 +00:00
ld a, 5
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
PlayMoveAnimation:
ld [wAnimationID], a
2014-05-22 22:13:20 +00:00
call Delay3
2014-06-16 20:25:46 +00:00
predef_jump MoveAnimation
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
InitBattle:
2015-08-31 02:38:41 +00:00
ld a, [wCurOpponent]
2014-05-22 22:13:20 +00:00
and a
jr z, DetermineWildOpponent
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
InitOpponent:
2015-08-31 02:38:41 +00:00
ld a, [wCurOpponent]
ld [wcf91], a
ld [wEnemyMonSpecies2], a
jr InitBattleCommon
2016-06-12 00:24:04 +00:00
DetermineWildOpponent:
ld a, [wd732]
2014-05-22 22:13:20 +00:00
bit 1, a
jr z, .asm_3ef2f
2014-05-25 17:51:53 +00:00
ld a, [hJoyHeld]
2014-09-13 07:50:56 +00:00
bit 1, a ; B button pressed?
2014-05-22 22:13:20 +00:00
ret nz
.asm_3ef2f
2014-09-13 07:50:56 +00:00
ld a, [wNumberOfNoRandomBattleStepsLeft]
2014-05-22 22:13:20 +00:00
and a
ret nz
2015-02-08 00:24:16 +00:00
callab TryDoWildEncounter
2014-05-22 22:13:20 +00:00
ret nz
2016-06-12 00:24:04 +00:00
InitBattleCommon:
2014-09-13 07:50:56 +00:00
ld a, [wMapPalOffset]
2014-05-22 22:13:20 +00:00
push af
2015-07-15 02:46:52 +00:00
ld hl, wLetterPrintingDelayFlags
2014-05-22 22:13:20 +00:00
ld a, [hl]
push af
res 1, [hl]
2015-02-08 00:24:16 +00:00
callab InitBattleVariables
ld a, [wEnemyMonSpecies2]
sub OPP_ID_OFFSET
2014-05-22 22:13:20 +00:00
jp c, InitWildBattle
2015-08-31 02:38:41 +00:00
ld [wTrainerClass], a
2014-05-22 22:13:20 +00:00
call GetTrainerInformation
callab ReadTrainer
2014-08-09 05:39:13 +00:00
call DoBattleTransitionAndInitBattleVariables
2014-05-22 22:13:20 +00:00
call _LoadTrainerPic
xor a
ld [wEnemyMonSpecies2], a
2015-07-24 03:48:35 +00:00
ld [hStartTileID], a
2014-05-22 22:13:20 +00:00
dec a
2014-08-09 05:39:13 +00:00
ld [wAICount], a
2015-07-18 20:52:03 +00:00
coord hl, 12, 0
predef CopyUncompressedPicToTilemap
2014-05-22 22:13:20 +00:00
ld a, $ff
ld [wEnemyMonPartyPos], a
2014-05-22 22:13:20 +00:00
ld a, $2
2015-08-31 02:38:41 +00:00
ld [wIsInBattle], a
2015-08-14 07:36:06 +00:00
jp _InitBattleCommon
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
InitWildBattle:
2014-05-22 22:13:20 +00:00
ld a, $1
2015-08-31 02:38:41 +00:00
ld [wIsInBattle], a
2014-08-09 05:39:13 +00:00
call LoadEnemyMonData
call DoBattleTransitionAndInitBattleVariables
2015-08-31 02:38:41 +00:00
ld a, [wCurOpponent]
2014-05-22 22:13:20 +00:00
cp MAROWAK
jr z, .isGhost
call IsGhostBattle
jr nz, .isNoGhost
.isGhost
2015-08-31 02:38:41 +00:00
ld hl, wMonHSpriteDim
2014-05-22 22:13:20 +00:00
ld a, $66
ld [hli], a ; write sprite dimensions
2014-08-09 05:39:13 +00:00
ld bc, GhostPic
2014-05-22 22:13:20 +00:00
ld a, c
ld [hli], a ; write front sprite pointer
ld [hl], b
ld hl, wEnemyMonNick ; set name to "GHOST"
2014-05-22 22:13:20 +00:00
ld a, "G"
ld [hli], a
ld a, "H"
ld [hli], a
ld a, "O"
ld [hli], a
ld a, "S"
ld [hli], a
ld a, "T"
ld [hli], a
ld [hl], "@"
ld a, [wcf91]
2014-05-22 22:13:20 +00:00
push af
ld a, MON_GHOST
ld [wcf91], a
2014-05-29 08:31:46 +00:00
ld de, vFrontPic
2014-05-22 22:13:20 +00:00
call LoadMonFrontSprite ; load ghost sprite
pop af
ld [wcf91], a
2014-05-22 22:13:20 +00:00
jr .spriteLoaded
.isNoGhost
2014-05-29 08:31:46 +00:00
ld de, vFrontPic
2014-05-22 22:13:20 +00:00
call LoadMonFrontSprite ; load mon sprite
.spriteLoaded
xor a
2015-08-31 02:38:41 +00:00
ld [wTrainerClass], a
2015-07-24 03:48:35 +00:00
ld [hStartTileID], a
2015-07-18 20:52:03 +00:00
coord hl, 12, 0
predef CopyUncompressedPicToTilemap
2014-05-22 22:13:20 +00:00
2014-08-09 05:39:13 +00:00
; common code that executes after init battle code specific to trainer or wild battles
2016-06-12 00:24:04 +00:00
_InitBattleCommon:
2015-08-12 09:16:56 +00:00
ld b, SET_PAL_BATTLE_BLACK
call RunPaletteCommand
2014-08-09 05:39:13 +00:00
call SlidePlayerAndEnemySilhouettesOnScreen
2014-05-22 22:13:20 +00:00
xor a
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
ld hl, .emptyString
2014-05-22 22:13:20 +00:00
call PrintText
call SaveScreenTilesToBuffer1
call ClearScreen
ld a, $98
ld [H_AUTOBGTRANSFERDEST + 1], a
2014-05-22 22:13:20 +00:00
ld a, $1
2014-08-09 05:39:13 +00:00
ld [H_AUTOBGTRANSFERENABLED], a
2014-05-22 22:13:20 +00:00
call Delay3
ld a, $9c
ld [H_AUTOBGTRANSFERDEST + 1], a
2014-05-22 22:13:20 +00:00
call LoadScreenTilesFromBuffer1
2015-07-18 20:52:03 +00:00
coord hl, 9, 7
2015-08-05 21:20:29 +00:00
lb bc, 5, 10
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2015-07-18 20:52:03 +00:00
coord hl, 1, 0
2015-08-05 21:20:29 +00:00
lb bc, 4, 10
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2014-05-23 22:34:35 +00:00
call ClearSprites
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-08-09 05:39:13 +00:00
dec a ; is it a wild battle?
call z, DrawEnemyHUDAndHPBar ; draw enemy HUD and HP bar if it's a wild battle
call StartBattle
callab EndOfBattle
2014-05-22 22:13:20 +00:00
pop af
2015-07-15 02:46:52 +00:00
ld [wLetterPrintingDelayFlags], a
2014-05-22 22:13:20 +00:00
pop af
2014-09-13 07:50:56 +00:00
ld [wMapPalOffset], a
2015-07-20 00:52:26 +00:00
ld a, [wSavedTilesetType]
2014-09-14 18:29:18 +00:00
ld [hTilesetType], a
2014-05-22 22:13:20 +00:00
scf
ret
2014-08-09 05:39:13 +00:00
.emptyString
2014-05-22 22:13:20 +00:00
db "@"
2016-06-12 00:24:04 +00:00
_LoadTrainerPic:
; wd033-wd034 contain pointer to pic
ld a, [wTrainerPicPointer]
2014-05-22 22:13:20 +00:00
ld e, a
ld a, [wTrainerPicPointer + 1]
2014-05-22 22:13:20 +00:00
ld d, a ; de contains pointer to trainer pic
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
2014-05-22 22:13:20 +00:00
and a
ld a, Bank(TrainerPics) ; this is where all the trainer pics are (not counting Red's)
jr z, .loadSprite
ld a, Bank(RedPicFront)
.loadSprite
call UncompressSpriteFromDE
2014-05-29 08:31:46 +00:00
ld de, vFrontPic
2014-05-22 22:13:20 +00:00
ld a, $77
ld c, a
jp LoadUncompressedSpriteData
; unreferenced
2016-06-12 00:24:04 +00:00
ResetCryModifiers:
2014-05-22 22:13:20 +00:00
xor a
2015-08-09 05:32:44 +00:00
ld [wFrequencyModifier], a
ld [wTempoModifier], a
2014-05-22 22:13:20 +00:00
jp PlaySound
2015-07-15 06:16:06 +00:00
; animates the mon "growing" out of the pokeball
2016-06-12 00:24:04 +00:00
AnimateSendingOutMon:
ld a, [wPredefRegisters]
2014-05-22 22:13:20 +00:00
ld h, a
ld a, [wPredefRegisters + 1]
2014-05-22 22:13:20 +00:00
ld l, a
2015-07-24 03:48:35 +00:00
ld a, [hStartTileID]
ld [hBaseTileID], a
2014-05-22 22:13:20 +00:00
ld b, $4c
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
and a
2015-07-24 03:48:35 +00:00
jr z, .notInBattle
2014-05-22 22:13:20 +00:00
add b
ld [hl], a
call Delay3
2015-07-24 03:48:35 +00:00
ld bc, -(SCREEN_WIDTH * 2 + 1)
2014-05-22 22:13:20 +00:00
add hl, bc
2015-07-24 03:48:35 +00:00
ld a, 1
2015-07-15 06:16:06 +00:00
ld [wDownscaledMonSize], a
2015-07-24 03:48:35 +00:00
lb bc, 3, 3
2015-07-15 06:16:06 +00:00
predef CopyDownscaledMonTiles
ld c, 4
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-07-24 03:48:35 +00:00
ld bc, -(SCREEN_WIDTH * 2 + 1)
2014-05-22 22:13:20 +00:00
add hl, bc
xor a
2015-07-15 06:16:06 +00:00
ld [wDownscaledMonSize], a
2015-07-24 03:48:35 +00:00
lb bc, 5, 5
2015-07-15 06:16:06 +00:00
predef CopyDownscaledMonTiles
ld c, 5
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-07-24 03:48:35 +00:00
ld bc, -(SCREEN_WIDTH * 2 + 1)
jr .next
.notInBattle
ld bc, -(SCREEN_WIDTH * 6 + 3)
.next
2014-05-22 22:13:20 +00:00
add hl, bc
2015-07-24 03:48:35 +00:00
ld a, [hBaseTileID]
2014-05-22 22:13:20 +00:00
add $31
jr CopyUncompressedPicToHL
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
CopyUncompressedPicToTilemap:
ld a, [wPredefRegisters]
2014-05-22 22:13:20 +00:00
ld h, a
ld a, [wPredefRegisters + 1]
2014-05-22 22:13:20 +00:00
ld l, a
2015-07-24 03:48:35 +00:00
ld a, [hStartTileID]
2016-06-12 00:24:04 +00:00
CopyUncompressedPicToHL:
2015-07-24 03:48:35 +00:00
lb bc, 7, 7
2015-07-14 07:16:19 +00:00
ld de, SCREEN_WIDTH
2014-05-22 22:13:20 +00:00
push af
2015-08-31 02:38:41 +00:00
ld a, [wSpriteFlipped]
2014-05-22 22:13:20 +00:00
and a
2015-07-24 03:48:35 +00:00
jr nz, .flipped
2014-05-22 22:13:20 +00:00
pop af
2015-07-24 03:48:35 +00:00
.loop
2014-05-22 22:13:20 +00:00
push bc
push hl
2015-07-24 03:48:35 +00:00
.innerLoop
2014-05-22 22:13:20 +00:00
ld [hl], a
add hl, de
inc a
dec c
2015-07-24 03:48:35 +00:00
jr nz, .innerLoop
2014-05-22 22:13:20 +00:00
pop hl
inc hl
pop bc
dec b
2015-07-24 03:48:35 +00:00
jr nz, .loop
2014-05-22 22:13:20 +00:00
ret
2015-06-11 22:41:33 +00:00
2015-07-24 03:48:35 +00:00
.flipped
2014-05-22 22:13:20 +00:00
push bc
2015-07-24 03:48:35 +00:00
ld b, 0
2014-05-22 22:13:20 +00:00
dec c
add hl, bc
pop bc
pop af
2015-07-24 03:48:35 +00:00
.flippedLoop
2014-05-22 22:13:20 +00:00
push bc
push hl
2015-07-24 03:48:35 +00:00
.flippedInnerLoop
2014-05-22 22:13:20 +00:00
ld [hl], a
add hl, de
inc a
dec c
2015-07-24 03:48:35 +00:00
jr nz, .flippedInnerLoop
2014-05-22 22:13:20 +00:00
pop hl
dec hl
pop bc
dec b
2015-07-24 03:48:35 +00:00
jr nz, .flippedLoop
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
LoadMonBackPic:
2014-05-29 08:31:46 +00:00
; Assumes the monster's attributes have
; been loaded with GetMonHeader.
ld a, [wBattleMonSpecies2]
ld [wcf91], a
2015-07-18 20:52:03 +00:00
coord hl, 1, 5
2015-08-05 21:20:29 +00:00
ld b, 7
ld c, 8
2014-05-22 22:13:20 +00:00
call ClearScreenArea
2015-08-31 02:38:41 +00:00
ld hl, wMonHBackSprite - wMonHeader
2014-05-22 22:13:20 +00:00
call UncompressMonSprite
predef ScaleSpriteByTwo
2014-05-29 08:31:46 +00:00
ld de, vBackPic
2014-05-22 22:13:20 +00:00
call InterlaceMergeSpriteBuffers ; combine the two buffers to a single 2bpp sprite
2014-05-29 08:31:46 +00:00
ld hl, vSprites
ld de, vBackPic
2014-05-22 22:13:20 +00:00
ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied
ld a, [H_LOADEDROMBANK]
ld b, a
jp CopyVideoData
2016-06-12 00:24:04 +00:00
JumpMoveEffect:
2014-08-09 05:39:13 +00:00
call _JumpMoveEffect
2014-05-22 22:13:20 +00:00
ld b, $1
ret
2016-06-12 00:24:04 +00:00
_JumpMoveEffect:
2015-03-31 18:50:49 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveEffect]
2014-05-22 22:13:20 +00:00
jr z, .next1
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2014-05-22 22:13:20 +00:00
.next1
2015-03-31 18:50:49 +00:00
dec a ; subtract 1, there is no special effect for 00
add a ; x2, 16bit pointers
2014-05-22 22:13:20 +00:00
ld hl, MoveEffectPointerTable
ld b, 0
ld c, a
add hl, bc
ld a, [hli]
ld h, [hl]
ld l, a
jp hl ; jump to special effect handler
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
MoveEffectPointerTable:
2014-05-22 22:13:20 +00:00
dw SleepEffect ; unused effect
dw PoisonEffect ; POISON_SIDE_EFFECT1
dw DrainHPEffect ; DRAIN_HP_EFFECT
dw FreezeBurnParalyzeEffect ; BURN_SIDE_EFFECT1
dw FreezeBurnParalyzeEffect ; FREEZE_SIDE_EFFECT
dw FreezeBurnParalyzeEffect ; PARALYZE_SIDE_EFFECT1
dw ExplodeEffect ; EXPLODE_EFFECT
dw DrainHPEffect ; DREAM_EATER_EFFECT
dw $0000 ; MIRROR_MOVE_EFFECT
dw StatModifierUpEffect ; ATTACK_UP1_EFFECT
dw StatModifierUpEffect ; DEFENSE_UP1_EFFECT
dw StatModifierUpEffect ; SPEED_UP1_EFFECT
dw StatModifierUpEffect ; SPECIAL_UP1_EFFECT
dw StatModifierUpEffect ; ACCURACY_UP1_EFFECT
dw StatModifierUpEffect ; EVASION_UP1_EFFECT
dw PayDayEffect ; PAY_DAY_EFFECT
dw $0000 ; SWIFT_EFFECT
dw StatModifierDownEffect ; ATTACK_DOWN1_EFFECT
dw StatModifierDownEffect ; DEFENSE_DOWN1_EFFECT
dw StatModifierDownEffect ; SPEED_DOWN1_EFFECT
dw StatModifierDownEffect ; SPECIAL_DOWN1_EFFECT
dw StatModifierDownEffect ; ACCURACY_DOWN1_EFFECT
dw StatModifierDownEffect ; EVASION_DOWN1_EFFECT
dw ConversionEffect ; CONVERSION_EFFECT
dw HazeEffect ; HAZE_EFFECT
dw BideEffect ; BIDE_EFFECT
dw ThrashPetalDanceEffect ; THRASH_PETAL_DANCE_EFFECT
dw SwitchAndTeleportEffect ; SWITCH_AND_TELEPORT_EFFECT
dw TwoToFiveAttacksEffect ; TWO_TO_FIVE_ATTACKS_EFFECT
dw TwoToFiveAttacksEffect ; unused effect
dw FlinchSideEffect ; FLINCH_SIDE_EFFECT1
2014-05-22 22:13:20 +00:00
dw SleepEffect ; SLEEP_EFFECT
dw PoisonEffect ; POISON_SIDE_EFFECT2
dw FreezeBurnParalyzeEffect ; BURN_SIDE_EFFECT2
dw FreezeBurnParalyzeEffect ; unused effect
dw FreezeBurnParalyzeEffect ; PARALYZE_SIDE_EFFECT2
dw FlinchSideEffect ; FLINCH_SIDE_EFFECT2
2014-05-22 22:13:20 +00:00
dw OneHitKOEffect ; OHKO_EFFECT
dw ChargeEffect ; CHARGE_EFFECT
dw $0000 ; SUPER_FANG_EFFECT
dw $0000 ; SPECIAL_DAMAGE_EFFECT
dw TrappingEffect ; TRAPPING_EFFECT
dw ChargeEffect ; FLY_EFFECT
dw TwoToFiveAttacksEffect ; ATTACK_TWICE_EFFECT
dw $0000 ; JUMP_KICK_EFFECT
dw MistEffect ; MIST_EFFECT
dw FocusEnergyEffect ; FOCUS_ENERGY_EFFECT
dw RecoilEffect ; RECOIL_EFFECT
dw ConfusionEffect ; CONFUSION_EFFECT
dw StatModifierUpEffect ; ATTACK_UP2_EFFECT
dw StatModifierUpEffect ; DEFENSE_UP2_EFFECT
dw StatModifierUpEffect ; SPEED_UP2_EFFECT
dw StatModifierUpEffect ; SPECIAL_UP2_EFFECT
dw StatModifierUpEffect ; ACCURACY_UP2_EFFECT
dw StatModifierUpEffect ; EVASION_UP2_EFFECT
dw HealEffect ; HEAL_EFFECT
dw TransformEffect ; TRANSFORM_EFFECT
dw StatModifierDownEffect ; ATTACK_DOWN2_EFFECT
dw StatModifierDownEffect ; DEFENSE_DOWN2_EFFECT
dw StatModifierDownEffect ; SPEED_DOWN2_EFFECT
dw StatModifierDownEffect ; SPECIAL_DOWN2_EFFECT
dw StatModifierDownEffect ; ACCURACY_DOWN2_EFFECT
dw StatModifierDownEffect ; EVASION_DOWN2_EFFECT
dw ReflectLightScreenEffect ; LIGHT_SCREEN_EFFECT
dw ReflectLightScreenEffect ; REFLECT_EFFECT
dw PoisonEffect ; POISON_EFFECT
dw ParalyzeEffect ; PARALYZE_EFFECT
dw StatModifierDownEffect ; ATTACK_DOWN_SIDE_EFFECT
dw StatModifierDownEffect ; DEFENSE_DOWN_SIDE_EFFECT
dw StatModifierDownEffect ; SPEED_DOWN_SIDE_EFFECT
dw StatModifierDownEffect ; SPECIAL_DOWN_SIDE_EFFECT
dw StatModifierDownEffect ; unused effect
dw StatModifierDownEffect ; unused effect
dw StatModifierDownEffect ; unused effect
dw StatModifierDownEffect ; unused effect
dw ConfusionSideEffect ; CONFUSION_SIDE_EFFECT
dw TwoToFiveAttacksEffect ; TWINEEDLE_EFFECT
dw $0000 ; unused effect
dw SubstituteEffect ; SUBSTITUTE_EFFECT
dw HyperBeamEffect ; HYPER_BEAM_EFFECT
dw RageEffect ; RAGE_EFFECT
dw MimicEffect ; MIMIC_EFFECT
dw $0000 ; METRONOME_EFFECT
dw LeechSeedEffect ; LEECH_SEED_EFFECT
dw SplashEffect ; SPLASH_EFFECT
dw DisableEffect ; DISABLE_EFFECT
2016-06-12 00:24:04 +00:00
SleepEffect:
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonStatus
2015-08-31 02:38:41 +00:00
ld bc, wEnemyBattleStatus2
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jp z, .sleepEffect
2014-08-09 05:39:13 +00:00
ld de, wBattleMonStatus
2015-08-31 02:38:41 +00:00
ld bc, wPlayerBattleStatus2
2014-05-22 22:13:20 +00:00
2015-01-20 19:21:16 +00:00
.sleepEffect
2014-05-22 22:13:20 +00:00
ld a, [bc]
2017-12-29 23:59:48 +00:00
bit NEEDS_TO_RECHARGE, a ; does the target need to recharge? (hyper beam)
res NEEDS_TO_RECHARGE, a ; target no longer needs to recharge
2014-05-22 22:13:20 +00:00
ld [bc], a
2015-01-20 19:21:16 +00:00
jr nz, .setSleepCounter ; if the target had to recharge, all hit tests will be skipped
; including the event where the target already has another status
2014-05-22 22:13:20 +00:00
ld a, [de]
ld b, a
and $7
2015-01-20 19:21:16 +00:00
jr z, .notAlreadySleeping ; can't affect a mon that is already asleep
2014-05-22 22:13:20 +00:00
ld hl, AlreadyAsleepText
jp PrintText
2015-01-20 19:21:16 +00:00
.notAlreadySleeping
2014-05-22 22:13:20 +00:00
ld a, b
and a
2015-01-20 19:21:16 +00:00
jr nz, .didntAffect ; can't affect a mon that is already statused
2014-05-22 22:13:20 +00:00
push de
2015-01-20 11:12:30 +00:00
call MoveHitTest ; apply accuracy tests
2014-05-22 22:13:20 +00:00
pop de
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr nz, .didntAffect
.setSleepCounter
2015-01-20 11:12:30 +00:00
; set target's sleep counter to a random number between 1 and 7
call BattleRandom
2015-01-23 03:05:13 +00:00
and $7
2015-01-20 19:21:16 +00:00
jr z, .setSleepCounter
2014-05-22 22:13:20 +00:00
ld [de], a
call PlayCurrentMoveAnimation2
2014-05-22 22:13:20 +00:00
ld hl, FellAsleepText
jp PrintText
2015-01-20 19:21:16 +00:00
.didntAffect
2014-05-22 22:13:20 +00:00
jp PrintDidntAffectText
2016-06-12 00:24:04 +00:00
FellAsleepText:
2014-05-22 22:13:20 +00:00
TX_FAR _FellAsleepText
db "@"
2016-06-12 00:24:04 +00:00
AlreadyAsleepText:
2014-05-22 22:13:20 +00:00
TX_FAR _AlreadyAsleepText
db "@"
2016-06-12 00:24:04 +00:00
PoisonEffect:
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonStatus
2015-08-31 02:38:41 +00:00
ld de, wPlayerMoveEffect
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .poisonEffect
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonStatus
2015-08-31 02:38:41 +00:00
ld de, wEnemyMoveEffect
2015-01-20 19:21:16 +00:00
.poisonEffect
2014-05-22 22:13:20 +00:00
call CheckTargetSubstitute
2017-06-24 20:01:43 +00:00
jr nz, .noEffect ; can't poison a substitute target
2014-05-22 22:13:20 +00:00
ld a, [hli]
ld b, a
and a
2015-01-20 19:21:16 +00:00
jr nz, .noEffect ; miss if target is already statused
2014-05-22 22:13:20 +00:00
ld a, [hli]
2017-06-24 20:01:43 +00:00
cp POISON ; can't poison a poison-type target
2015-01-20 19:21:16 +00:00
jr z, .noEffect
2014-05-22 22:13:20 +00:00
ld a, [hld]
2017-06-24 20:01:43 +00:00
cp POISON ; can't poison a poison-type target
2015-01-20 19:21:16 +00:00
jr z, .noEffect
2014-05-22 22:13:20 +00:00
ld a, [de]
cp POISON_SIDE_EFFECT1
ld b, $34 ; ~20% chance of poisoning
2015-01-20 19:21:16 +00:00
jr z, .sideEffectTest
2014-05-22 22:13:20 +00:00
cp POISON_SIDE_EFFECT2
ld b, $67 ; ~40% chance of poisoning
2015-01-20 19:21:16 +00:00
jr z, .sideEffectTest
2014-05-22 22:13:20 +00:00
push hl
push de
2015-01-20 11:12:30 +00:00
call MoveHitTest ; apply accuracy tests
2014-05-22 22:13:20 +00:00
pop de
pop hl
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr nz, .didntAffect
jr .inflictPoison
.sideEffectTest
2015-01-23 03:05:13 +00:00
call BattleRandom
2015-01-20 11:12:30 +00:00
cp b ; was side effect successful?
2014-05-22 22:13:20 +00:00
ret nc
2015-01-20 19:21:16 +00:00
.inflictPoison
2014-05-22 22:13:20 +00:00
dec hl
2015-01-20 11:12:30 +00:00
set 3, [hl] ; mon is now poisoned
2014-05-22 22:13:20 +00:00
push de
dec de
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld b, ANIM_C7
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus3
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-08-31 02:38:41 +00:00
ld de, wPlayerToxicCounter
2015-01-20 19:21:16 +00:00
jr nz, .ok
ld b, ANIM_A9
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus3
2016-06-12 04:30:05 +00:00
ld de, wEnemyToxicCounter
2015-01-20 19:21:16 +00:00
.ok
cp TOXIC
2015-01-20 19:21:16 +00:00
jr nz, .normalPoison ; done if move is not Toxic
2017-12-29 23:59:48 +00:00
set BADLY_POISONED, [hl] ; else set Toxic battstatus
2014-05-22 22:13:20 +00:00
xor a
ld [de], a
ld hl, BadlyPoisonedText
2016-06-12 04:30:05 +00:00
jr .continue
2015-01-20 19:21:16 +00:00
.normalPoison
2014-05-22 22:13:20 +00:00
ld hl, PoisonedText
2016-06-12 04:30:05 +00:00
.continue
2014-05-22 22:13:20 +00:00
pop de
ld a, [de]
cp POISON_EFFECT
2016-06-12 04:30:05 +00:00
jr z, .regularPoisonEffect
2014-05-22 22:13:20 +00:00
ld a, b
call PlayBattleAnimation2
2014-05-22 22:13:20 +00:00
jp PrintText
2016-06-12 04:30:05 +00:00
.regularPoisonEffect
call PlayCurrentMoveAnimation2
2014-05-22 22:13:20 +00:00
jp PrintText
2015-01-20 19:21:16 +00:00
.noEffect
2014-05-22 22:13:20 +00:00
ld a, [de]
cp POISON_EFFECT
ret nz
2015-01-20 19:21:16 +00:00
.didntAffect
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
jp PrintDidntAffectText
2016-06-12 00:24:04 +00:00
PoisonedText:
2014-05-22 22:13:20 +00:00
TX_FAR _PoisonedText
db "@"
2016-06-12 00:24:04 +00:00
BadlyPoisonedText:
2014-05-22 22:13:20 +00:00
TX_FAR _BadlyPoisonedText
db "@"
2016-06-12 00:24:04 +00:00
DrainHPEffect:
2015-07-19 18:56:13 +00:00
jpab DrainHPEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ExplodeEffect:
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonHP
2015-08-31 02:38:41 +00:00
ld de, wPlayerBattleStatus2
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .faintUser
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonHP
2015-08-31 02:38:41 +00:00
ld de, wEnemyBattleStatus2
2015-01-20 19:21:16 +00:00
.faintUser
2014-05-22 22:13:20 +00:00
xor a
ld [hli], a ; set the mon's HP to 0
ld [hli], a
inc hl
ld [hl], a ; set mon's status to 0
ld a, [de]
2017-12-29 23:59:48 +00:00
res SEEDED, a ; clear mon's leech seed status
2014-05-22 22:13:20 +00:00
ld [de], a
ret
2016-06-12 00:24:04 +00:00
FreezeBurnParalyzeEffect:
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2015-01-20 11:12:30 +00:00
call CheckTargetSubstitute ; test bit 4 of d063/d068 flags [target has substitute flag]
ret nz ; return if they have a substitute, can't effect them
2015-03-31 18:50:49 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jp nz, opponentAttacker
ld a, [wEnemyMonStatus]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 11:12:30 +00:00
jp nz, CheckDefrost ; can't inflict status if opponent is already statused
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveType]
2014-05-22 22:13:20 +00:00
ld b, a
ld a, [wEnemyMonType1]
2015-01-20 11:12:30 +00:00
cp b ; do target type 1 and move type match?
ret z ; return if they match (an ice move can't freeze an ice-type, body slam can't paralyze a normal-type, etc.)
ld a, [wEnemyMonType2]
2015-01-20 11:12:30 +00:00
cp b ; do target type 2 and move type match?
ret z ; return if they match
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveEffect]
cp PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those
2015-01-20 11:12:30 +00:00
ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance
jr c, .next1 ; branch ahead if this is a 10% chance effect..
ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance
sub $1e ; subtract $1E to map to equivalent 10% chance effects
2014-05-22 22:13:20 +00:00
.next1
2015-01-23 03:05:13 +00:00
push af
2015-01-20 11:12:30 +00:00
call BattleRandom ; get random 8bit value for probability test
cp b
2015-01-23 03:05:13 +00:00
pop bc
2015-01-20 11:12:30 +00:00
ret nc ; do nothing if random value is >= 1A or 4D [no status applied]
ld a, b ; what type of effect is this?
cp BURN_SIDE_EFFECT1
2014-05-22 22:13:20 +00:00
jr z, .burn
cp FREEZE_SIDE_EFFECT
2014-05-22 22:13:20 +00:00
jr z, .freeze
2015-01-23 03:05:13 +00:00
; .paralyze
2014-05-22 22:13:20 +00:00
ld a, 1 << PAR
ld [wEnemyMonStatus], a
2015-01-20 11:12:30 +00:00
call QuarterSpeedDueToParalysis ; quarter speed of affected mon
ld a, ANIM_A9
2015-01-23 03:05:13 +00:00
call PlayBattleAnimation
2015-01-20 11:12:30 +00:00
jp PrintMayNotAttackText ; print paralysis text
2014-05-22 22:13:20 +00:00
.burn
ld a, 1 << BRN
ld [wEnemyMonStatus], a
2015-01-20 11:12:30 +00:00
call HalveAttackDueToBurn ; halve attack of affected mon
ld a, ANIM_A9
2015-01-23 03:05:13 +00:00
call PlayBattleAnimation
2014-05-22 22:13:20 +00:00
ld hl, BurnedText
jp PrintText
.freeze
call ClearHyperBeam ; resets hyper beam (recharge) condition from target
2014-05-22 22:13:20 +00:00
ld a, 1 << FRZ
ld [wEnemyMonStatus], a
ld a, ANIM_A9
2015-01-23 03:05:13 +00:00
call PlayBattleAnimation
2014-05-22 22:13:20 +00:00
ld hl, FrozenText
jp PrintText
2016-06-12 00:24:04 +00:00
opponentAttacker:
2015-01-20 11:12:30 +00:00
ld a, [wBattleMonStatus] ; mostly same as above with addresses swapped for opponent
2014-05-22 22:13:20 +00:00
and a
jp nz, CheckDefrost
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveType]
2014-05-22 22:13:20 +00:00
ld b, a
ld a, [wBattleMonType1]
2014-05-22 22:13:20 +00:00
cp b
ret z
ld a, [wBattleMonType2]
2014-05-22 22:13:20 +00:00
cp b
ret z
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
cp PARALYZE_SIDE_EFFECT1 + 1
2014-05-22 22:13:20 +00:00
ld b, $1a
jr c, .next1
ld b, $4d
sub $1e
2014-05-22 22:13:20 +00:00
.next1
push af
call BattleRandom
2014-05-22 22:13:20 +00:00
cp b
pop bc
ret nc
ld a, b
cp BURN_SIDE_EFFECT1
2014-05-22 22:13:20 +00:00
jr z, .burn
cp FREEZE_SIDE_EFFECT
2014-05-22 22:13:20 +00:00
jr z, .freeze
ld a, 1 << PAR
ld [wBattleMonStatus], a
2014-08-09 05:39:13 +00:00
call QuarterSpeedDueToParalysis
2014-05-22 22:13:20 +00:00
jp PrintMayNotAttackText
.burn
ld a, 1 << BRN
ld [wBattleMonStatus], a
2014-08-09 05:39:13 +00:00
call HalveAttackDueToBurn
2014-05-22 22:13:20 +00:00
ld hl, BurnedText
jp PrintText
.freeze
2015-01-20 11:12:30 +00:00
; hyper beam bits aren't reseted for opponent's side
2014-05-22 22:13:20 +00:00
ld a, 1 << FRZ
ld [wBattleMonStatus], a
2014-05-22 22:13:20 +00:00
ld hl, FrozenText
jp PrintText
2016-06-12 00:24:04 +00:00
BurnedText:
2014-05-22 22:13:20 +00:00
TX_FAR _BurnedText
db "@"
2016-06-12 00:24:04 +00:00
FrozenText:
2014-05-22 22:13:20 +00:00
TX_FAR _FrozenText
db "@"
2016-06-12 00:24:04 +00:00
CheckDefrost:
2015-01-20 11:12:30 +00:00
; any fire-type move that has a chance inflict burn (all but Fire Spin) will defrost a frozen target
and 1 << FRZ ; are they frozen?
2015-01-20 11:12:30 +00:00
ret z ; return if so
2015-03-31 18:50:49 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr nz, .opponent
;player [attacker]
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveType]
sub FIRE
2015-01-20 11:12:30 +00:00
ret nz ; return if type of move used isn't fire
2016-07-28 03:33:48 +00:00
ld [wEnemyMonStatus], a ; set opponent status to 00 ["defrost" a frozen monster]
ld hl, wEnemyMon1Status
ld a, [wEnemyMonPartyPos]
ld bc, wEnemyMon2 - wEnemyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
xor a
2015-01-20 11:12:30 +00:00
ld [hl], a ; clear status in roster
2014-05-22 22:13:20 +00:00
ld hl, FireDefrostedText
jr .common
.opponent
2016-07-28 03:33:48 +00:00
ld a, [wEnemyMoveType] ; same as above with addresses swapped
sub FIRE
2014-05-22 22:13:20 +00:00
ret nz
ld [wBattleMonStatus], a
ld hl, wPartyMon1Status
2014-05-22 22:13:20 +00:00
ld a, [wPlayerMonNumber]
ld bc, wPartyMon2 - wPartyMon1
2014-05-22 22:13:20 +00:00
call AddNTimes
xor a
ld [hl], a
ld hl, FireDefrostedText
.common
jp PrintText
2016-06-12 00:24:04 +00:00
FireDefrostedText:
2014-05-22 22:13:20 +00:00
TX_FAR _FireDefrostedText
db "@"
2016-06-12 00:24:04 +00:00
StatModifierUpEffect:
2014-08-09 05:39:13 +00:00
ld hl, wPlayerMonStatMods
2015-08-31 02:38:41 +00:00
ld de, wPlayerMoveEffect
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .statModifierUpEffect
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonStatMods
2015-08-31 02:38:41 +00:00
ld de, wEnemyMoveEffect
2015-01-20 19:21:16 +00:00
.statModifierUpEffect
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-01-23 03:05:13 +00:00
sub ATTACK_UP1_EFFECT
cp EVASION_UP1_EFFECT + $3 - ATTACK_UP1_EFFECT ; covers all +1 effects
2015-01-20 19:21:16 +00:00
jr c, .incrementStatMod
2015-01-20 19:34:56 +00:00
sub ATTACK_UP2_EFFECT - ATTACK_UP1_EFFECT ; map +2 effects to equivalent +1 effect
2015-01-20 19:21:16 +00:00
.incrementStatMod
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
add hl, bc
ld b, [hl]
2015-01-20 11:12:30 +00:00
inc b ; increment corresponding stat mod
2014-05-22 22:13:20 +00:00
ld a, $d
2015-01-20 11:12:30 +00:00
cp b ; can't raise stat past +6 ($d or 13)
jp c, PrintNothingHappenedText
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-01-20 19:34:56 +00:00
cp ATTACK_UP1_EFFECT + $8 ; is it a +2 effect?
2015-01-20 19:21:16 +00:00
jr c, .ok
2015-01-20 11:12:30 +00:00
inc b ; if so, increment stat mod again
2014-05-22 22:13:20 +00:00
ld a, $d
2015-01-20 11:12:30 +00:00
cp b ; unless it's already +6
2015-01-20 19:21:16 +00:00
jr nc, .ok
2014-05-22 22:13:20 +00:00
ld b, a
2015-01-20 19:21:16 +00:00
.ok
2014-05-22 22:13:20 +00:00
ld [hl], b
ld a, c
cp $4
2015-01-20 19:21:16 +00:00
jr nc, UpdateStatDone ; jump if mod affected is evasion/accuracy
2014-05-22 22:13:20 +00:00
push hl
ld hl, wBattleMonAttack + 1
ld de, wPlayerMonUnmodifiedAttack
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .pointToStats
ld hl, wEnemyMonAttack + 1
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonUnmodifiedAttack
2015-01-20 19:21:16 +00:00
.pointToStats
2014-05-22 22:13:20 +00:00
push bc
sla c
ld b, $0
2015-01-20 11:12:30 +00:00
add hl, bc ; hl = modified stat
2014-05-22 22:13:20 +00:00
ld a, c
add e
ld e, a
2015-01-20 19:21:16 +00:00
jr nc, .checkIf999
2015-01-20 11:12:30 +00:00
inc d ; de = unmodified (original) stat
2015-01-20 19:21:16 +00:00
.checkIf999
2014-05-22 22:13:20 +00:00
pop bc
ld a, [hld]
sub 999 % $100 ; check if stat is already 999
2015-01-20 19:21:16 +00:00
jr nz, .recalculateStat
2014-05-22 22:13:20 +00:00
ld a, [hl]
sbc 999 / $100
jp z, RestoreOriginalStatModifier
2015-01-20 19:21:16 +00:00
.recalculateStat ; recalculate affected stat
; paralysis and burn penalties, as well as badge boosts are ignored
2014-05-22 22:13:20 +00:00
push hl
push bc
2014-08-09 05:39:13 +00:00
ld hl, StatModifierRatios
2014-05-22 22:13:20 +00:00
dec b
sla b
ld c, b
ld b, $0
add hl, bc
pop bc
xor a
2015-06-11 22:41:33 +00:00
ld [H_MULTIPLICAND], a
2014-05-22 22:13:20 +00:00
ld a, [de]
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
ld a, [hli]
2015-06-11 22:41:33 +00:00
ld [H_MULTIPLIER], a
2014-05-22 22:13:20 +00:00
call Multiply
ld a, [hl]
2015-06-11 22:41:33 +00:00
ld [H_DIVISOR], a
2014-05-22 22:13:20 +00:00
ld b, $4
call Divide
pop hl
2015-01-23 03:05:13 +00:00
; cap at 999
ld a, [H_PRODUCT + 3]
sub 999 % $100
ld a, [H_PRODUCT + 2]
sbc 999 / $100
2015-01-20 19:21:16 +00:00
jp c, UpdateStat
2014-05-22 22:13:20 +00:00
ld a, 999 / $100
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
ld a, 999 % $100
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
UpdateStat:
ld a, [H_PRODUCT + 2]
2014-05-22 22:13:20 +00:00
ld [hli], a
ld a, [H_PRODUCT + 3]
2014-05-22 22:13:20 +00:00
ld [hl], a
pop hl
2016-06-12 00:24:04 +00:00
UpdateStatDone:
2014-05-22 22:13:20 +00:00
ld b, c
inc b
call PrintStatText
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus2
ld de, wPlayerMoveNum
2015-07-12 22:51:04 +00:00
ld bc, wPlayerMonMinimized
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .asm_3f4e6
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus2
ld de, wEnemyMoveNum
2015-07-12 22:51:04 +00:00
ld bc, wEnemyMonMinimized
2014-05-22 22:13:20 +00:00
.asm_3f4e6
ld a, [de]
cp MINIMIZE
jr nz, .asm_3f4f9
2015-07-12 22:51:04 +00:00
; if a substitute is up, slide off the substitute and show the mon pic before
; playing the minimize animation
2017-12-29 23:59:48 +00:00
bit HAS_SUBSTITUTE_UP, [hl]
2014-05-22 22:13:20 +00:00
push af
push bc
2015-07-12 22:51:04 +00:00
ld hl, HideSubstituteShowMonAnim
ld b, BANK(HideSubstituteShowMonAnim)
2014-05-22 22:13:20 +00:00
push de
2015-07-12 22:51:04 +00:00
call nz, Bankswitch
2014-05-22 22:13:20 +00:00
pop de
.asm_3f4f9
2015-02-08 00:24:16 +00:00
call PlayCurrentMoveAnimation
2014-05-22 22:13:20 +00:00
ld a, [de]
cp MINIMIZE
2015-01-20 19:21:16 +00:00
jr nz, .applyBadgeBoostsAndStatusPenalties
2014-05-22 22:13:20 +00:00
pop bc
ld a, $1
ld [bc], a
2015-07-12 22:51:04 +00:00
ld hl, ReshowSubstituteAnim
ld b, BANK(ReshowSubstituteAnim)
2014-05-22 22:13:20 +00:00
pop af
call nz, Bankswitch
2015-01-20 19:21:16 +00:00
.applyBadgeBoostsAndStatusPenalties
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 11:12:30 +00:00
call z, ApplyBadgeStatBoosts ; whenever the player uses a stat-up move, badge boosts get reapplied again to every stat,
; even to those not affected by the stat-up move (will be boosted further)
2014-05-22 22:13:20 +00:00
ld hl, MonsStatsRoseText
call PrintText
2015-01-20 11:12:30 +00:00
2015-01-23 03:05:13 +00:00
; these shouldn't be here
2015-01-20 11:12:30 +00:00
call QuarterSpeedDueToParalysis ; apply speed penalty to the player whose turn is not, if it's paralyzed
jp HalveAttackDueToBurn ; apply attack penalty to the player whose turn is not, if it's burned
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
RestoreOriginalStatModifier:
2014-05-22 22:13:20 +00:00
pop hl
dec [hl]
2016-06-12 00:24:04 +00:00
PrintNothingHappenedText:
2014-05-22 22:13:20 +00:00
ld hl, NothingHappenedText
jp PrintText
2016-06-12 00:24:04 +00:00
MonsStatsRoseText:
2014-05-22 22:13:20 +00:00
TX_FAR _MonsStatsRoseText
2015-07-03 19:58:50 +00:00
TX_ASM
2014-05-22 22:13:20 +00:00
ld hl, GreatlyRoseText
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveEffect]
2016-06-12 04:30:05 +00:00
jr z, .playerTurn
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2016-06-12 04:30:05 +00:00
.playerTurn
2014-05-22 22:13:20 +00:00
cp ATTACK_DOWN1_EFFECT
ret nc
ld hl, RoseText
ret
2016-06-12 00:24:04 +00:00
GreatlyRoseText:
2016-07-18 06:17:03 +00:00
TX_DELAY
2014-05-22 22:13:20 +00:00
TX_FAR _GreatlyRoseText
2016-06-12 04:30:05 +00:00
; fallthrough
2016-06-12 00:24:04 +00:00
RoseText:
2014-05-22 22:13:20 +00:00
TX_FAR _RoseText
db "@"
2016-06-12 00:24:04 +00:00
StatModifierDownEffect:
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonStatMods
2015-08-31 02:38:41 +00:00
ld de, wPlayerMoveEffect
ld bc, wEnemyBattleStatus1
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .statModifierDownEffect
2014-08-09 05:39:13 +00:00
ld hl, wPlayerMonStatMods
2015-08-31 02:38:41 +00:00
ld de, wEnemyMoveEffect
ld bc, wPlayerBattleStatus1
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2015-01-20 19:21:16 +00:00
jr z, .statModifierDownEffect
call BattleRandom
cp $40 ; 1/4 chance to miss by in regular battle
2015-01-20 19:21:16 +00:00
jp c, MoveMissed
.statModifierDownEffect
2015-01-20 11:12:30 +00:00
call CheckTargetSubstitute ; can't hit through substitute
2015-01-20 19:21:16 +00:00
jp nz, MoveMissed
2014-05-22 22:13:20 +00:00
ld a, [de]
cp ATTACK_DOWN_SIDE_EFFECT
2015-01-20 19:21:16 +00:00
jr c, .nonSideEffect
call BattleRandom
2015-01-20 11:12:30 +00:00
cp $55 ; 85/256 chance for side effects
2015-01-20 19:21:16 +00:00
jp nc, CantLowerAnymore
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-01-20 11:12:30 +00:00
sub ATTACK_DOWN_SIDE_EFFECT ; map each stat to 0-3
2015-01-20 19:21:16 +00:00
jr .decrementStatMod
.nonSideEffect ; non-side effects only
2014-05-22 22:13:20 +00:00
push hl
push de
push bc
2015-01-20 11:12:30 +00:00
call MoveHitTest ; apply accuracy tests
2014-05-22 22:13:20 +00:00
pop bc
pop de
pop hl
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jp nz, MoveMissed
2014-05-22 22:13:20 +00:00
ld a, [bc]
2017-12-29 23:59:48 +00:00
bit INVULNERABLE, a ; fly/dig
2015-01-20 19:21:16 +00:00
jp nz, MoveMissed
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-01-23 03:05:13 +00:00
sub ATTACK_DOWN1_EFFECT
2017-06-24 20:01:43 +00:00
cp EVASION_DOWN1_EFFECT + $3 - ATTACK_DOWN1_EFFECT ; covers all -1 effects
2015-01-20 19:21:16 +00:00
jr c, .decrementStatMod
sub ATTACK_DOWN2_EFFECT - ATTACK_DOWN1_EFFECT ; map -2 effects to corresponding -1 effect
2015-01-20 19:21:16 +00:00
.decrementStatMod
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
add hl, bc
ld b, [hl]
2015-01-20 11:12:30 +00:00
dec b ; dec corresponding stat mod
2015-01-20 19:21:16 +00:00
jp z, CantLowerAnymore ; if stat mod is 1 (-6), can't lower anymore
2014-05-22 22:13:20 +00:00
ld a, [de]
cp ATTACK_DOWN2_EFFECT - $16 ; $24
2015-01-20 19:21:16 +00:00
jr c, .ok
cp EVASION_DOWN2_EFFECT + $5 ; $44
2015-01-20 19:21:16 +00:00
jr nc, .ok
2015-01-20 11:12:30 +00:00
dec b ; stat down 2 effects only (dec mod again)
2015-01-20 19:21:16 +00:00
jr nz, .ok
2015-01-20 11:12:30 +00:00
inc b ; increment mod to 1 (-6) if it would become 0 (-7)
2015-01-20 19:21:16 +00:00
.ok
2015-01-23 03:05:13 +00:00
ld [hl], b ; save modified mod
2014-05-22 22:13:20 +00:00
ld a, c
2015-01-23 03:05:13 +00:00
cp $4
jr nc, UpdateLoweredStatDone ; jump for evasion/accuracy
2014-05-22 22:13:20 +00:00
push hl
push de
ld hl, wEnemyMonAttack + 1
2014-08-09 05:39:13 +00:00
ld de, wEnemyMonUnmodifiedAttack
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .pointToStat
ld hl, wBattleMonAttack + 1
ld de, wPlayerMonUnmodifiedAttack
2015-01-20 19:21:16 +00:00
.pointToStat
2014-05-22 22:13:20 +00:00
push bc
sla c
ld b, $0
2015-01-20 11:12:30 +00:00
add hl, bc ; hl = modified stat
2014-05-22 22:13:20 +00:00
ld a, c
add e
ld e, a
2016-06-12 04:30:05 +00:00
jr nc, .noCarry
2015-01-20 11:12:30 +00:00
inc d ; de = unmodified stat
2016-06-12 04:30:05 +00:00
.noCarry
2014-05-22 22:13:20 +00:00
pop bc
ld a, [hld]
2015-01-20 11:12:30 +00:00
sub $1 ; can't lower stat below 1 (-6)
2015-01-20 19:21:16 +00:00
jr nz, .recalculateStat
2014-05-22 22:13:20 +00:00
ld a, [hl]
and a
jp z, CantLowerAnymore_Pop
2015-01-20 19:21:16 +00:00
.recalculateStat
2015-01-20 11:12:30 +00:00
; recalculate affected stat
; paralysis and burn penalties, as well as badge boosts are ignored
2014-05-22 22:13:20 +00:00
push hl
push bc
2014-08-09 05:39:13 +00:00
ld hl, StatModifierRatios
2014-05-22 22:13:20 +00:00
dec b
sla b
ld c, b
ld b, $0
add hl, bc
pop bc
xor a
2015-06-11 22:41:33 +00:00
ld [H_MULTIPLICAND], a
2014-05-22 22:13:20 +00:00
ld a, [de]
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
inc de
ld a, [de]
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
ld a, [hli]
2015-06-11 22:41:33 +00:00
ld [H_MULTIPLIER], a
2014-05-22 22:13:20 +00:00
call Multiply
ld a, [hl]
2015-06-11 22:41:33 +00:00
ld [H_DIVISOR], a
2014-05-22 22:13:20 +00:00
ld b, $4
call Divide
pop hl
ld a, [H_PRODUCT + 3]
2014-05-22 22:13:20 +00:00
ld b, a
ld a, [H_PRODUCT + 2]
2014-05-22 22:13:20 +00:00
or b
jp nz, UpdateLoweredStat
ld [H_MULTIPLICAND + 1], a
2014-05-22 22:13:20 +00:00
ld a, $1
ld [H_MULTIPLICAND + 2], a
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
UpdateLoweredStat:
ld a, [H_PRODUCT + 2]
2014-05-22 22:13:20 +00:00
ld [hli], a
ld a, [H_PRODUCT + 3]
2014-05-22 22:13:20 +00:00
ld [hl], a
pop de
pop hl
2016-06-12 00:24:04 +00:00
UpdateLoweredStatDone:
2014-05-22 22:13:20 +00:00
ld b, c
inc b
push de
call PrintStatText
2014-05-22 22:13:20 +00:00
pop de
ld a, [de]
cp $44
2015-01-20 19:21:16 +00:00
jr nc, .ApplyBadgeBoostsAndStatusPenalties
call PlayCurrentMoveAnimation2
2015-01-20 19:21:16 +00:00
.ApplyBadgeBoostsAndStatusPenalties
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 11:12:30 +00:00
call nz, ApplyBadgeStatBoosts ; whenever the player uses a stat-down move, badge boosts get reapplied again to every stat,
; even to those not affected by the stat-up move (will be boosted further)
2014-05-22 22:13:20 +00:00
ld hl, MonsStatsFellText
call PrintText
2015-01-23 03:05:13 +00:00
; These where probably added given that a stat-down move affecting speed or attack will override
2015-01-20 11:12:30 +00:00
; the stat penalties from paralysis and burn respectively.
2015-01-23 03:05:13 +00:00
; But they are always called regardless of the stat affected by the stat-down move.
2014-08-09 05:39:13 +00:00
call QuarterSpeedDueToParalysis
jp HalveAttackDueToBurn
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
CantLowerAnymore_Pop:
2014-05-22 22:13:20 +00:00
pop de
pop hl
inc [hl]
2016-06-12 00:24:04 +00:00
CantLowerAnymore:
2014-05-22 22:13:20 +00:00
ld a, [de]
cp ATTACK_DOWN_SIDE_EFFECT
ret nc
ld hl, NothingHappenedText
jp PrintText
2016-06-12 00:24:04 +00:00
MoveMissed:
2014-05-22 22:13:20 +00:00
ld a, [de]
cp $44
ret nc
2015-03-31 18:50:49 +00:00
jp ConditionalPrintButItFailed
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
MonsStatsFellText:
2014-05-22 22:13:20 +00:00
TX_FAR _MonsStatsFellText
2015-07-03 19:58:50 +00:00
TX_ASM
2014-05-22 22:13:20 +00:00
ld hl, FellText
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveEffect]
2016-06-12 04:30:05 +00:00
jr z, .playerTurn
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveEffect]
2016-06-12 04:30:05 +00:00
.playerTurn
; check if the move's effect decreases a stat by 2
cp BIDE_EFFECT
2014-05-22 22:13:20 +00:00
ret c
2016-06-12 04:30:05 +00:00
cp ATTACK_DOWN_SIDE_EFFECT
2014-05-22 22:13:20 +00:00
ret nc
ld hl, GreatlyFellText
ret
2016-06-12 00:24:04 +00:00
GreatlyFellText:
2016-07-18 06:17:03 +00:00
TX_DELAY
2014-05-22 22:13:20 +00:00
TX_FAR _GreatlyFellText
2016-06-12 04:30:05 +00:00
; fallthrough
2016-06-12 00:24:04 +00:00
FellText:
2014-05-22 22:13:20 +00:00
TX_FAR _FellText
db "@"
2016-06-12 00:24:04 +00:00
PrintStatText:
2014-05-22 22:13:20 +00:00
ld hl, StatsTextStrings
2015-08-05 21:20:29 +00:00
ld c, "@"
2016-06-12 04:30:05 +00:00
.findStatName_outer
2014-05-22 22:13:20 +00:00
dec b
2016-06-12 04:30:05 +00:00
jr z, .foundStatName
.findStatName_inner
2014-05-22 22:13:20 +00:00
ld a, [hli]
cp c
2016-06-12 04:30:05 +00:00
jr z, .findStatName_outer
jr .findStatName_inner
.foundStatName
ld de, wcf4b
2014-05-22 22:13:20 +00:00
ld bc, $a
jp CopyData
2016-06-12 00:24:04 +00:00
StatsTextStrings:
2014-05-22 22:13:20 +00:00
db "ATTACK@"
db "DEFENSE@"
db "SPEED@"
db "SPECIAL@"
db "ACCURACY@"
db "EVADE@"
2016-06-12 00:24:04 +00:00
StatModifierRatios:
2014-05-22 22:13:20 +00:00
; first byte is numerator, second byte is denominator
db 25, 100 ; 0.25
db 28, 100 ; 0.28
db 33, 100 ; 0.33
db 40, 100 ; 0.40
db 50, 100 ; 0.50
db 66, 100 ; 0.66
db 1, 1 ; 1.00
db 15, 10 ; 1.50
db 2, 1 ; 2.00
db 25, 10 ; 2.50
db 3, 1 ; 3.00
db 35, 10 ; 3.50
db 4, 1 ; 4.00
2016-06-12 00:24:04 +00:00
BideEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2015-02-07 10:43:08 +00:00
ld de, wPlayerBideAccumulatedDamage
2014-08-09 05:39:13 +00:00
ld bc, wPlayerNumAttacksLeft
2014-05-22 22:13:20 +00:00
ld a, [H_WHOSETURN]
and a
2015-01-20 19:21:16 +00:00
jr z, .bideEffect
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2015-02-07 10:43:08 +00:00
ld de, wEnemyBideAccumulatedDamage
2014-08-09 05:39:13 +00:00
ld bc, wEnemyNumAttacksLeft
2015-01-20 19:21:16 +00:00
.bideEffect
2017-12-29 23:59:48 +00:00
set STORING_ENERGY, [hl] ; mon is now using bide
2014-05-22 22:13:20 +00:00
xor a
ld [de], a
inc de
ld [de], a
2015-08-31 02:38:41 +00:00
ld [wPlayerMoveEffect], a
ld [wEnemyMoveEffect], a
call BattleRandom
2014-05-22 22:13:20 +00:00
and $1
inc a
inc a
2015-01-20 11:12:30 +00:00
ld [bc], a ; set Bide counter to 2 or 3 at random
2014-05-22 22:13:20 +00:00
ld a, [H_WHOSETURN]
add XSTATITEM_ANIM
jp PlayBattleAnimation2
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ThrashPetalDanceEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2014-08-09 05:39:13 +00:00
ld de, wPlayerNumAttacksLeft
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .thrashPetalDanceEffect
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-08-09 05:39:13 +00:00
ld de, wEnemyNumAttacksLeft
2015-01-20 19:21:16 +00:00
.thrashPetalDanceEffect
2017-12-29 23:59:48 +00:00
set THRASHING_ABOUT, [hl] ; mon is now using thrash/petal dance
call BattleRandom
2015-01-23 03:05:13 +00:00
and $1
2014-05-22 22:13:20 +00:00
inc a
inc a
2015-01-20 11:12:30 +00:00
ld [de], a ; set thrash/petal dance counter to 2 or 3 at random
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
add ANIM_B0
jp PlayBattleAnimation2
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
SwitchAndTeleportEffect:
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2016-06-12 04:30:05 +00:00
jr nz, .handleEnemy
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
2016-06-12 04:30:05 +00:00
jr nz, .notWildBattle1
2015-08-31 02:38:41 +00:00
ld a, [wCurEnemyLVL]
2014-05-22 22:13:20 +00:00
ld b, a
2014-08-09 05:39:13 +00:00
ld a, [wBattleMonLevel]
2016-06-12 04:30:05 +00:00
cp b ; is the player's level greater than the enemy's level?
jr nc, .playerMoveWasSuccessful ; if so, teleport will always succeed
2014-05-22 22:13:20 +00:00
add b
ld c, a
2016-06-12 04:30:05 +00:00
inc c ; c = sum of player level and enemy level
.rejectionSampleLoop1
call BattleRandom
2016-06-12 04:30:05 +00:00
cp c ; get a random number between 0 and c
jr nc, .rejectionSampleLoop1
2014-05-22 22:13:20 +00:00
srl b
2016-10-17 05:30:32 +00:00
srl b ; b = enemyLevel / 4
cp b ; is rand[0, playerLevel + enemyLevel) >= (enemyLevel / 4)?
2016-06-12 04:30:05 +00:00
jr nc, .playerMoveWasSuccessful ; if so, allow teleporting
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveNum]
2014-05-22 22:13:20 +00:00
cp TELEPORT
jp nz, PrintDidntAffectText
jp PrintButItFailedText_
2016-06-12 04:30:05 +00:00
.playerMoveWasSuccessful
2014-05-22 22:13:20 +00:00
call ReadPlayerMonCurHPAndStatus
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld [wEscapedFromBattle], a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveNum]
2016-06-12 04:30:05 +00:00
jr .playAnimAndPrintText
.notWildBattle1
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
ld hl, IsUnaffectedText
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveNum]
2014-05-22 22:13:20 +00:00
cp TELEPORT
jp nz, PrintText
jp PrintButItFailedText_
2016-06-12 04:30:05 +00:00
.handleEnemy
2015-08-31 02:38:41 +00:00
ld a, [wIsInBattle]
2014-05-22 22:13:20 +00:00
dec a
2016-06-12 04:30:05 +00:00
jr nz, .notWildBattle2
2014-08-09 05:39:13 +00:00
ld a, [wBattleMonLevel]
2014-05-22 22:13:20 +00:00
ld b, a
2015-08-31 02:38:41 +00:00
ld a, [wCurEnemyLVL]
2014-05-22 22:13:20 +00:00
cp b
2016-06-12 04:30:05 +00:00
jr nc, .enemyMoveWasSuccessful
2014-05-22 22:13:20 +00:00
add b
ld c, a
inc c
2016-06-12 04:30:05 +00:00
.rejectionSampleLoop2
call BattleRandom
2014-05-22 22:13:20 +00:00
cp c
2016-06-12 04:30:05 +00:00
jr nc, .rejectionSampleLoop2
2014-05-22 22:13:20 +00:00
srl b
srl b
cp b
2016-06-12 04:30:05 +00:00
jr nc, .enemyMoveWasSuccessful
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
2014-05-22 22:13:20 +00:00
cp TELEPORT
jp nz, PrintDidntAffectText
jp PrintButItFailedText_
2016-06-12 04:30:05 +00:00
.enemyMoveWasSuccessful
2014-05-22 22:13:20 +00:00
call ReadPlayerMonCurHPAndStatus
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-05-22 22:13:20 +00:00
inc a
2014-08-09 05:39:13 +00:00
ld [wEscapedFromBattle], a
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
2016-06-12 04:30:05 +00:00
jr .playAnimAndPrintText
.notWildBattle2
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
ld hl, IsUnaffectedText
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
2014-05-22 22:13:20 +00:00
cp TELEPORT
jp nz, PrintText
2015-03-31 18:50:49 +00:00
jp ConditionalPrintButItFailed
2016-06-12 04:30:05 +00:00
.playAnimAndPrintText
2014-05-22 22:13:20 +00:00
push af
2015-01-23 03:05:13 +00:00
call PlayBattleAnimation
ld c, 20
2014-05-22 22:13:20 +00:00
call DelayFrames
pop af
2014-08-09 05:39:13 +00:00
ld hl, RanFromBattleText
2014-05-22 22:13:20 +00:00
cp TELEPORT
2016-06-12 04:30:05 +00:00
jr z, .printText
2014-08-09 05:39:13 +00:00
ld hl, RanAwayScaredText
2014-05-22 22:13:20 +00:00
cp ROAR
2016-06-12 04:30:05 +00:00
jr z, .printText
2014-08-09 05:39:13 +00:00
ld hl, WasBlownAwayText
2016-06-12 04:30:05 +00:00
.printText
2014-05-22 22:13:20 +00:00
jp PrintText
2016-06-12 00:24:04 +00:00
RanFromBattleText:
2014-05-22 22:13:20 +00:00
TX_FAR _RanFromBattleText
db "@"
2016-06-12 00:24:04 +00:00
RanAwayScaredText:
2014-05-22 22:13:20 +00:00
TX_FAR _RanAwayScaredText
db "@"
2016-06-12 00:24:04 +00:00
WasBlownAwayText:
2014-05-22 22:13:20 +00:00
TX_FAR _WasBlownAwayText
db "@"
2016-06-12 00:24:04 +00:00
TwoToFiveAttacksEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2014-08-09 05:39:13 +00:00
ld de, wPlayerNumAttacksLeft
2015-02-07 10:43:08 +00:00
ld bc, wPlayerNumHits
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .twoToFiveAttacksEffect
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-08-09 05:39:13 +00:00
ld de, wEnemyNumAttacksLeft
2015-02-07 10:43:08 +00:00
ld bc, wEnemyNumHits
2015-01-20 19:21:16 +00:00
.twoToFiveAttacksEffect
2017-12-29 23:59:48 +00:00
bit ATTACKING_MULTIPLE_TIMES, [hl] ; is mon attacking multiple times?
2014-05-22 22:13:20 +00:00
ret nz
2017-12-29 23:59:48 +00:00
set ATTACKING_MULTIPLE_TIMES, [hl] ; mon is now attacking multiple times
2015-08-31 02:38:41 +00:00
ld hl, wPlayerMoveEffect
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-01-20 19:21:16 +00:00
jr z, .setNumberOfHits
2015-08-31 02:38:41 +00:00
ld hl, wEnemyMoveEffect
2015-01-20 19:21:16 +00:00
.setNumberOfHits
2014-05-22 22:13:20 +00:00
ld a, [hl]
cp TWINEEDLE_EFFECT
2015-01-20 19:21:16 +00:00
jr z, .twineedle
2014-05-22 22:13:20 +00:00
cp ATTACK_TWICE_EFFECT
2015-01-20 19:21:16 +00:00
ld a, $2 ; number of hits it's always 2 for ATTACK_TWICE_EFFECT
jr z, .saveNumberOfHits
2015-01-23 03:05:13 +00:00
; for TWO_TO_FIVE_ATTACKS_EFFECT 3/8 chance for 2 and 3 hits, and 1/8 chance for 4 and 5 hits
call BattleRandom
2015-01-23 03:05:13 +00:00
and $3
cp $2
2016-06-12 04:30:05 +00:00
jr c, .gotNumHits
; if the number of hits was greater than 2, re-roll again for a lower chance
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
2016-06-12 04:30:05 +00:00
.gotNumHits
2014-05-22 22:13:20 +00:00
inc a
inc a
2015-01-20 19:21:16 +00:00
.saveNumberOfHits
2014-05-22 22:13:20 +00:00
ld [de], a
ld [bc], a
ret
2015-01-20 19:21:16 +00:00
.twineedle
ld a, POISON_SIDE_EFFECT1
ld [hl], a ; set Twineedle's effect to poison effect
jr .saveNumberOfHits
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
FlinchSideEffect:
2014-05-22 22:13:20 +00:00
call CheckTargetSubstitute
ret nz
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
ld de, wPlayerMoveEffect
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .flinchSideEffect
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
ld de, wEnemyMoveEffect
.flinchSideEffect
2014-05-22 22:13:20 +00:00
ld a, [de]
cp FLINCH_SIDE_EFFECT1
ld b, $1a ; ~10% chance of flinch
jr z, .gotEffectChance
2014-05-22 22:13:20 +00:00
ld b, $4d ; ~30% chance of flinch
.gotEffectChance
call BattleRandom
2014-05-22 22:13:20 +00:00
cp b
ret nc
2017-12-29 23:59:48 +00:00
set FLINCHED, [hl] ; set mon's status to flinching
2015-01-20 19:21:16 +00:00
call ClearHyperBeam
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
OneHitKOEffect:
2015-07-19 18:56:13 +00:00
jpab OneHitKOEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ChargeEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
ld de, wPlayerMoveEffect
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld b, XSTATITEM_ANIM
jr z, .chargeEffect
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
ld de, wEnemyMoveEffect
ld b, ANIM_AF
.chargeEffect
2017-12-29 23:59:48 +00:00
set CHARGING_UP, [hl]
2014-05-22 22:13:20 +00:00
ld a, [de]
dec de ; de contains enemy or player MOVENUM
cp FLY_EFFECT
jr nz, .notFly
2017-12-29 23:59:48 +00:00
set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig)
ld b, TELEPORT ; load Teleport's animation
.notFly
2014-05-22 22:13:20 +00:00
ld a, [de]
cp DIG
jr nz, .notDigOrFly
2017-12-29 23:59:48 +00:00
set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig)
ld b, ANIM_C0
.notDigOrFly
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-05-22 22:13:20 +00:00
ld a, b
2015-01-23 03:05:13 +00:00
call PlayBattleAnimation
2014-05-22 22:13:20 +00:00
ld a, [de]
2015-07-16 03:04:58 +00:00
ld [wChargeMoveNum], a
2014-08-09 05:39:13 +00:00
ld hl, ChargeMoveEffectText
2014-05-22 22:13:20 +00:00
jp PrintText
2016-06-12 00:24:04 +00:00
ChargeMoveEffectText:
2014-05-22 22:13:20 +00:00
TX_FAR _ChargeMoveEffectText
2015-07-03 19:58:50 +00:00
TX_ASM
2015-07-16 03:04:58 +00:00
ld a, [wChargeMoveNum]
2014-05-22 22:13:20 +00:00
cp RAZOR_WIND
2014-08-09 05:39:13 +00:00
ld hl, MadeWhirlwindText
2016-06-12 04:30:05 +00:00
jr z, .gotText
2014-05-22 22:13:20 +00:00
cp SOLARBEAM
2014-08-09 05:39:13 +00:00
ld hl, TookInSunlightText
2016-06-12 04:30:05 +00:00
jr z, .gotText
2014-05-22 22:13:20 +00:00
cp SKULL_BASH
2014-08-09 05:39:13 +00:00
ld hl, LoweredItsHeadText
2016-06-12 04:30:05 +00:00
jr z, .gotText
2014-05-22 22:13:20 +00:00
cp SKY_ATTACK
2014-08-09 05:39:13 +00:00
ld hl, SkyAttackGlowingText
2016-06-12 04:30:05 +00:00
jr z, .gotText
2014-05-22 22:13:20 +00:00
cp FLY
2014-08-09 05:39:13 +00:00
ld hl, FlewUpHighText
2016-06-12 04:30:05 +00:00
jr z, .gotText
2014-05-22 22:13:20 +00:00
cp DIG
2014-08-09 05:39:13 +00:00
ld hl, DugAHoleText
2016-06-12 04:30:05 +00:00
.gotText
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
MadeWhirlwindText:
2014-05-22 22:13:20 +00:00
TX_FAR _MadeWhirlwindText
db "@"
2016-06-12 00:24:04 +00:00
TookInSunlightText:
2014-05-22 22:13:20 +00:00
TX_FAR _TookInSunlightText
db "@"
2016-06-12 00:24:04 +00:00
LoweredItsHeadText:
2014-05-22 22:13:20 +00:00
TX_FAR _LoweredItsHeadText
db "@"
2016-06-12 00:24:04 +00:00
SkyAttackGlowingText:
2014-05-22 22:13:20 +00:00
TX_FAR _SkyAttackGlowingText
db "@"
2016-06-12 00:24:04 +00:00
FlewUpHighText:
2014-05-22 22:13:20 +00:00
TX_FAR _FlewUpHighText
db "@"
2016-06-12 00:24:04 +00:00
DugAHoleText:
2014-05-22 22:13:20 +00:00
TX_FAR _DugAHoleText
db "@"
2016-06-12 00:24:04 +00:00
TrappingEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
2014-08-09 05:39:13 +00:00
ld de, wPlayerNumAttacksLeft
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .trappingEffect
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
2014-08-09 05:39:13 +00:00
ld de, wEnemyNumAttacksLeft
.trappingEffect
2017-12-29 23:59:48 +00:00
bit USING_TRAPPING_MOVE, [hl]
2014-05-22 22:13:20 +00:00
ret nz
2015-06-11 22:41:33 +00:00
call ClearHyperBeam ; since this effect is called before testing whether the move will hit,
; the target won't need to recharge even if the trapping move missed
2017-12-29 23:59:48 +00:00
set USING_TRAPPING_MOVE, [hl] ; mon is now using a trapping move
call BattleRandom ; 3/8 chance for 2 and 3 attacks, and 1/8 chance for 4 and 5 attacks
2014-05-22 22:13:20 +00:00
and $3
cp $2
jr c, .setTrappingCounter
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
.setTrappingCounter
2014-05-22 22:13:20 +00:00
inc a
ld [de], a
ret
2016-06-12 00:24:04 +00:00
MistEffect:
2015-07-19 18:56:13 +00:00
jpab MistEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
FocusEnergyEffect:
2015-07-19 18:56:13 +00:00
jpab FocusEnergyEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
RecoilEffect:
2015-07-19 18:56:13 +00:00
jpab RecoilEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ConfusionSideEffect:
call BattleRandom
2016-06-12 04:30:05 +00:00
cp $19 ; ~10% chance
2014-05-22 22:13:20 +00:00
ret nc
jr ConfusionSideEffectSuccess
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ConfusionEffect:
2014-05-22 22:13:20 +00:00
call CheckTargetSubstitute
jr nz, ConfusionEffectFailed
2014-05-22 22:13:20 +00:00
call MoveHitTest
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
jr nz, ConfusionEffectFailed
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ConfusionSideEffectSuccess:
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus1
ld bc, wEnemyConfusedCounter
ld a, [wPlayerMoveEffect]
jr z, .confuseTarget
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus1
ld bc, wPlayerConfusedCounter
ld a, [wEnemyMoveEffect]
.confuseTarget
2017-12-29 23:59:48 +00:00
bit CONFUSED, [hl] ; is mon confused?
jr nz, ConfusionEffectFailed
2017-12-29 23:59:48 +00:00
set CONFUSED, [hl] ; mon is now confused
2014-05-22 22:13:20 +00:00
push af
call BattleRandom
2015-06-11 22:41:33 +00:00
and $3
2014-05-22 22:13:20 +00:00
inc a
inc a
ld [bc], a ; confusion status will last 2-5 turns
2014-05-22 22:13:20 +00:00
pop af
cp CONFUSION_SIDE_EFFECT
call nz, PlayCurrentMoveAnimation2
2014-08-09 05:39:13 +00:00
ld hl, BecameConfusedText
2014-05-22 22:13:20 +00:00
jp PrintText
2016-06-12 00:24:04 +00:00
BecameConfusedText:
2014-05-22 22:13:20 +00:00
TX_FAR _BecameConfusedText
db "@"
2016-06-12 00:24:04 +00:00
ConfusionEffectFailed:
2014-05-22 22:13:20 +00:00
cp CONFUSION_SIDE_EFFECT
ret z
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
2015-03-31 18:50:49 +00:00
jp ConditionalPrintButItFailed
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ParalyzeEffect:
2015-07-19 18:56:13 +00:00
jpab ParalyzeEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
SubstituteEffect:
2015-07-19 18:56:13 +00:00
jpab SubstituteEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
HyperBeamEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus2
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .hyperBeamEffect
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus2
.hyperBeamEffect
2017-12-29 23:59:48 +00:00
set NEEDS_TO_RECHARGE, [hl] ; mon now needs to recharge
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
ClearHyperBeam:
2014-05-22 22:13:20 +00:00
push hl
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus2
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2016-06-12 04:30:05 +00:00
jr z, .playerTurn
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus2
2016-06-12 04:30:05 +00:00
.playerTurn
2017-12-29 23:59:48 +00:00
res NEEDS_TO_RECHARGE, [hl] ; mon no longer needs to recharge
2014-05-22 22:13:20 +00:00
pop hl
ret
2016-06-12 00:24:04 +00:00
RageEffect:
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus2
2014-05-22 22:13:20 +00:00
ld a, [H_WHOSETURN]
and a
jr z, .player
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus2
2014-05-22 22:13:20 +00:00
.player
2017-12-29 23:59:48 +00:00
set USING_RAGE, [hl] ; mon is now in "rage" mode
2014-05-22 22:13:20 +00:00
ret
2016-06-12 00:24:04 +00:00
MimicEffect:
ld c, 50
2014-05-22 22:13:20 +00:00
call DelayFrames
call MoveHitTest
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
2016-06-12 04:30:05 +00:00
jr nz, .mimicMissed
2014-05-22 22:13:20 +00:00
ld a, [H_WHOSETURN]
and a
ld hl, wBattleMonMoves
2015-08-31 02:38:41 +00:00
ld a, [wPlayerBattleStatus1]
2016-06-12 04:30:05 +00:00
jr nz, .enemyTurn
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
2016-06-12 04:30:05 +00:00
jr nz, .letPlayerChooseMove
ld hl, wEnemyMonMoves
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus1]
2016-06-12 04:30:05 +00:00
.enemyTurn
2017-12-29 23:59:48 +00:00
bit INVULNERABLE, a
2016-06-12 04:30:05 +00:00
jr nz, .mimicMissed
.getRandomMove
2014-05-22 22:13:20 +00:00
push hl
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
ld c, a
ld b, $0
add hl, bc
ld a, [hl]
pop hl
and a
2016-06-12 04:30:05 +00:00
jr z, .getRandomMove
2014-05-22 22:13:20 +00:00
ld d, a
ld a, [H_WHOSETURN]
and a
ld hl, wBattleMonMoves
2014-05-22 22:13:20 +00:00
ld a, [wPlayerMoveListIndex]
2016-06-12 04:30:05 +00:00
jr z, .playerTurn
ld hl, wEnemyMonMoves
2014-05-22 22:13:20 +00:00
ld a, [wEnemyMoveListIndex]
2016-06-12 04:30:05 +00:00
jr .playerTurn
.letPlayerChooseMove
2015-08-31 02:38:41 +00:00
ld a, [wEnemyBattleStatus1]
2017-12-29 23:59:48 +00:00
bit INVULNERABLE, a
2016-06-12 04:30:05 +00:00
jr nz, .mimicMissed
2014-05-22 22:13:20 +00:00
ld a, [wCurrentMenuItem]
push af
ld a, $1
ld [wMoveMenuType], a
call MoveSelectionMenu
call LoadScreenTilesFromBuffer1
ld hl, wEnemyMonMoves
2014-05-22 22:13:20 +00:00
ld a, [wCurrentMenuItem]
ld c, a
ld b, $0
add hl, bc
ld d, [hl]
pop af
ld hl, wBattleMonMoves
2016-06-12 04:30:05 +00:00
.playerTurn
2014-05-22 22:13:20 +00:00
ld c, a
ld b, $0
add hl, bc
ld a, d
ld [hl], a
ld [wd11e], a
2014-05-22 22:13:20 +00:00
call GetMoveName
2015-02-08 00:24:16 +00:00
call PlayCurrentMoveAnimation
2014-05-22 22:13:20 +00:00
ld hl, MimicLearnedMoveText
jp PrintText
2016-06-12 04:30:05 +00:00
.mimicMissed
2014-05-22 22:13:20 +00:00
jp PrintButItFailedText_
2016-06-12 00:24:04 +00:00
MimicLearnedMoveText:
2014-05-22 22:13:20 +00:00
TX_FAR _MimicLearnedMoveText
db "@"
2016-06-12 00:24:04 +00:00
LeechSeedEffect:
2015-07-19 18:56:13 +00:00
jpab LeechSeedEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
SplashEffect:
2015-02-08 00:24:16 +00:00
call PlayCurrentMoveAnimation
2014-05-22 22:13:20 +00:00
jp PrintNoEffectText
2016-06-12 00:24:04 +00:00
DisableEffect:
2014-05-22 22:13:20 +00:00
call MoveHitTest
2015-08-31 02:38:41 +00:00
ld a, [wMoveMissed]
2014-05-22 22:13:20 +00:00
and a
jr nz, .moveMissed
2015-08-31 02:38:41 +00:00
ld de, wEnemyDisabledMove
ld hl, wEnemyMonMoves
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .disableEffect
2015-08-31 02:38:41 +00:00
ld de, wPlayerDisabledMove
ld hl, wBattleMonMoves
.disableEffect
; no effect if target already has a move disabled
2014-05-22 22:13:20 +00:00
ld a, [de]
and a
jr nz, .moveMissed
.pickMoveToDisable
2014-05-22 22:13:20 +00:00
push hl
call BattleRandom
2014-05-22 22:13:20 +00:00
and $3
ld c, a
ld b, $0
add hl, bc
ld a, [hl]
pop hl
and a
jr z, .pickMoveToDisable ; loop until a non-00 move slot is found
ld [wd11e], a ; store move number
2014-05-22 22:13:20 +00:00
push hl
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2014-08-09 05:39:13 +00:00
ld hl, wBattleMonPP
2015-06-11 22:41:33 +00:00
jr nz, .enemyTurn
2015-02-07 10:43:08 +00:00
ld a, [wLinkState]
cp LINK_STATE_BATTLING
pop hl ; wEnemyMonMoves
jr nz, .playerTurnNotLinkBattle
2015-06-11 22:41:33 +00:00
; .playerTurnLinkBattle
2014-05-22 22:13:20 +00:00
push hl
2014-08-09 05:39:13 +00:00
ld hl, wEnemyMonPP
.enemyTurn
2014-05-22 22:13:20 +00:00
push hl
ld a, [hli]
or [hl]
inc hl
or [hl]
inc hl
or [hl]
and $3f
pop hl ; wBattleMonPP or wEnemyMonPP
jr z, .moveMissedPopHL ; nothing to do if all moves have no PP left
2014-05-22 22:13:20 +00:00
add hl, bc
ld a, [hl]
pop hl
and a
jr z, .pickMoveToDisable ; pick another move if this one had 0 PP
.playerTurnNotLinkBattle
; non-link battle enemies have unlimited PP so the previous checks aren't needed
call BattleRandom
2014-05-22 22:13:20 +00:00
and $7
inc a ; 1-8 turns disabled
inc c ; move 1-4 will be disabled
2015-06-11 22:41:33 +00:00
swap c
2015-08-31 02:38:41 +00:00
add c ; map disabled move to high nibble of wEnemyDisabledMove / wPlayerDisabledMove
2014-05-22 22:13:20 +00:00
ld [de], a
call PlayCurrentMoveAnimation2
ld hl, wPlayerDisabledMoveNumber
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr nz, .printDisableText
inc hl ; wEnemyDisabledMoveNumber
.printDisableText
ld a, [wd11e] ; move number
2015-06-11 22:41:33 +00:00
ld [hl], a
2014-05-22 22:13:20 +00:00
call GetMoveName
2014-08-09 05:39:13 +00:00
ld hl, MoveWasDisabledText
2014-05-22 22:13:20 +00:00
jp PrintText
.moveMissedPopHL
2014-05-22 22:13:20 +00:00
pop hl
.moveMissed
2014-05-22 22:13:20 +00:00
jp PrintButItFailedText_
2016-06-12 00:24:04 +00:00
MoveWasDisabledText:
2014-05-22 22:13:20 +00:00
TX_FAR _MoveWasDisabledText
db "@"
2016-06-12 00:24:04 +00:00
PayDayEffect:
2015-07-19 18:56:13 +00:00
jpab PayDayEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ConversionEffect:
2015-07-19 18:56:13 +00:00
jpab ConversionEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
HazeEffect:
2015-07-19 18:56:13 +00:00
jpab HazeEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
HealEffect:
2015-07-19 18:56:13 +00:00
jpab HealEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
TransformEffect:
2015-07-19 18:56:13 +00:00
jpab TransformEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
ReflectLightScreenEffect:
2015-07-19 18:56:13 +00:00
jpab ReflectLightScreenEffect_
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
NothingHappenedText:
2014-05-22 22:13:20 +00:00
TX_FAR _NothingHappenedText
db "@"
2016-06-12 00:24:04 +00:00
PrintNoEffectText:
2014-05-22 22:13:20 +00:00
ld hl, NoEffectText
jp PrintText
2016-06-12 00:24:04 +00:00
NoEffectText:
2014-05-22 22:13:20 +00:00
TX_FAR _NoEffectText
db "@"
2016-06-12 00:24:04 +00:00
ConditionalPrintButItFailed:
2015-03-31 18:28:42 +00:00
ld a, [wMoveDidntMiss]
2014-05-22 22:13:20 +00:00
and a
2015-03-31 18:50:49 +00:00
ret nz ; return if the side effect failed, yet the attack was successful
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
PrintButItFailedText_:
2014-05-22 22:13:20 +00:00
ld hl, ButItFailedText
jp PrintText
2016-06-12 00:24:04 +00:00
ButItFailedText:
2014-05-22 22:13:20 +00:00
TX_FAR _ButItFailedText
db "@"
2016-06-12 00:24:04 +00:00
PrintDidntAffectText:
2014-05-22 22:13:20 +00:00
ld hl, DidntAffectText
jp PrintText
2016-06-12 00:24:04 +00:00
DidntAffectText:
2014-05-22 22:13:20 +00:00
TX_FAR _DidntAffectText
db "@"
2016-06-12 00:24:04 +00:00
IsUnaffectedText:
2014-05-22 22:13:20 +00:00
TX_FAR _IsUnaffectedText
db "@"
2016-06-12 00:24:04 +00:00
PrintMayNotAttackText:
2014-08-09 05:39:13 +00:00
ld hl, ParalyzedMayNotAttackText
2014-05-22 22:13:20 +00:00
jp PrintText
2016-06-12 00:24:04 +00:00
ParalyzedMayNotAttackText:
2014-05-22 22:13:20 +00:00
TX_FAR _ParalyzedMayNotAttackText
db "@"
2016-06-12 00:24:04 +00:00
CheckTargetSubstitute:
2014-05-22 22:13:20 +00:00
push hl
2015-08-31 02:38:41 +00:00
ld hl, wEnemyBattleStatus2
2015-06-11 22:41:33 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
jr z, .next1
2015-08-31 02:38:41 +00:00
ld hl, wPlayerBattleStatus2
2014-05-22 22:13:20 +00:00
.next1
2017-12-29 23:59:48 +00:00
bit HAS_SUBSTITUTE_UP, [hl]
2014-05-22 22:13:20 +00:00
pop hl
ret
2016-06-12 00:24:04 +00:00
PlayCurrentMoveAnimation2:
2015-03-31 19:09:43 +00:00
; animation at MOVENUM will be played unless MOVENUM is 0
; plays wAnimationType 3 or 6
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveNum]
jr z, .notEnemyTurn
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
.notEnemyTurn
2014-05-22 22:13:20 +00:00
and a
ret z
2016-06-12 00:24:04 +00:00
PlayBattleAnimation2:
; play animation ID at a and animation type 6 or 3
2015-08-31 02:38:41 +00:00
ld [wAnimationID], a
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
ld a, $6
2015-03-31 19:09:43 +00:00
jr z, .storeAnimationType
2014-05-22 22:13:20 +00:00
ld a, $3
2015-03-31 19:09:43 +00:00
.storeAnimationType
ld [wAnimationType], a
jp PlayBattleAnimationGotID
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
PlayCurrentMoveAnimation:
; animation at MOVENUM will be played unless MOVENUM is 0
; resets wAnimationType
2014-05-22 22:13:20 +00:00
xor a
2015-03-31 19:09:43 +00:00
ld [wAnimationType], a
2014-08-09 05:39:13 +00:00
ld a, [H_WHOSETURN]
2014-05-22 22:13:20 +00:00
and a
2015-08-31 02:38:41 +00:00
ld a, [wPlayerMoveNum]
2015-02-08 00:24:16 +00:00
jr z, .notEnemyTurn
2015-08-31 02:38:41 +00:00
ld a, [wEnemyMoveNum]
2015-02-08 00:24:16 +00:00
.notEnemyTurn
2014-05-22 22:13:20 +00:00
and a
ret z
2016-06-12 00:24:04 +00:00
PlayBattleAnimation:
; play animation ID at a and predefined animation type
2015-08-31 02:38:41 +00:00
ld [wAnimationID], a
2014-05-22 22:13:20 +00:00
2016-06-12 00:24:04 +00:00
PlayBattleAnimationGotID:
2015-08-31 02:38:41 +00:00
; play animation at wAnimationID
2014-05-22 22:13:20 +00:00
push hl
push de
push bc
predef MoveAnimation
2014-05-22 22:13:20 +00:00
pop bc
pop de
pop hl
ret