ref: c2efe700ac1c5cca88bac710b98388a99665741e
parent: 52add272c6bca00d2ea827ef7fa4611a4bc41b47
parent: ce9940a2eb89caa9f53507a6d6071f8eaf85ee48
author: yenatch <yenatch@gmail.com>
date: Wed Apr 1 08:56:42 EDT 2015
Merge pull request #90 from xCrystal/master Rename/split battle and move effect files. Battle functions, AI, and attack animations
--- a/engine/battle/1.asm
+++ /dev/null
@@ -1,104 +1,0 @@
-DrainHPEffect_: ; 783f (1:783f)
- ld hl, W_DAMAGE
- ld a, [hl]
- srl a ; divide damage by 2
- ld [hli], a
- ld a, [hl]
- rr a
- ld [hld], a
- or [hl] ; is damage 0?
- jr nz, .getAttackerHP
-; if damage is 0, increase to 1 so that the attacker gains at least 1 HP
- inc hl
- inc [hl]
-.getAttackerHP
- ld hl, wBattleMonHP
- ld de, wBattleMonMaxHP
- ld a, [H_WHOSETURN]
- and a
- jp z, .addDamageToAttackerHP
- ld hl, wEnemyMonHP
- ld de, wEnemyMonMaxHP
-.addDamageToAttackerHP
- ld bc, wHPBarOldHP+1
-; copy current HP to wHPBarOldHP
- ld a, [hli]
- ld [bc], a
- ld a, [hl]
- dec bc
- ld [bc], a
-; copy max HP to wHPBarMaxHP
- ld a, [de]
- dec bc
- ld [bc], a
- inc de
- ld a, [de]
- dec bc
- ld [bc], a
-; add damage to attacker's HP and copy new HP to wHPBarNewHP
- ld a, [W_DAMAGE + 1]
- ld b, [hl]
- add b
- ld [hld], a
- ld [wHPBarNewHP], a
- ld a, [W_DAMAGE]
- ld b, [hl]
- adc b
- ld [hli], a
- ld [wHPBarNewHP+1], a
- jr c, .capToMaxHP ; if HP > 65,535, cap to max HP
-; compare HP with max HP
- ld a, [hld]
- ld b, a
- ld a, [de]
- dec de
- sub b
- ld a, [hli]
- ld b, a
- ld a, [de]
- inc de
- sbc b
- jr nc, .next
-.capToMaxHP
- ld a, [de]
- ld [hld], a
- ld [wHPBarNewHP], a
- dec de
- ld a, [de]
- ld [hli], a
- ld [wHPBarNewHP+1], a
- inc de
-.next
- ld a, [H_WHOSETURN]
- and a
- hlCoord 10, 9
- ld a, $1
- jr z, .next2
- hlCoord 2, 2
- xor a
-.next2
- ld [wHPBarType], a
- predef UpdateHPBar2
- predef DrawPlayerHUDAndHPBar
- predef DrawEnemyHUDAndHPBar
- callab ReadPlayerMonCurHPAndStatus
- ld hl, SuckedHealthText
- ld a, [H_WHOSETURN]
- and a
- ld a, [W_PLAYERMOVEEFFECT]
- jr z, .next3
- ld a, [W_ENEMYMOVEEFFECT]
-.next3
- cp DREAM_EATER_EFFECT
- jr nz, .printText
- ld hl, DreamWasEatenText
-.printText
- jp PrintText
-
-SuckedHealthText: ; 78dc (1:78dc)
- TX_FAR _SuckedHealthText
- db "@"
-
-DreamWasEatenText: ; 78e1 (1:78e1)
- TX_FAR _DreamWasEatenText
- db "@"
--- a/engine/battle/14.asm
+++ /dev/null
@@ -1,94 +1,0 @@
-InitBattleVariables: ; 525af (14:65af)
- ld a, [hTilesetType]
- ld [wd0d4], a
- xor a
- ld [wcd6a], a
- ld [wBattleResult], a
- ld hl, wcc2b
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wListScrollOffset], a
- ld [wCriticalHitOrOHKO], a
- ld [wBattleMonSpecies], a
- ld [wPartyGainExpFlags], a
- ld [wPlayerMonNumber], a
- ld [wEscapedFromBattle], a
- ld [wMapPalOffset], a
- ld hl, wcf1d
- ld [hli], a
- ld [hl], a
- ld hl, wccd3
- ld b, $3c
-.loop
- ld [hli], a
- dec b
- jr nz, .loop
- inc a
- ld [wccd9], a
- ld a, [W_CURMAP]
- cp SAFARI_ZONE_EAST
- jr c, .notSafariBattle
- cp SAFARI_ZONE_REST_HOUSE_1
- jr nc, .notSafariBattle
- ld a, $2 ; safari battle
- ld [W_BATTLETYPE], a
-.notSafariBattle
- ld hl, PlayBattleMusic
- ld b, BANK(PlayBattleMusic)
- jp Bankswitch
-
-ParalyzeEffect_: ; 52601 (14:6601)
- ld hl, wEnemyMonStatus
- ld de, W_PLAYERMOVETYPE
- ld a, [H_WHOSETURN]
- and a
- jp z, .next
- ld hl, wBattleMonStatus
- ld de, W_ENEMYMOVETYPE
-.next
- ld a, [hl]
- and a ; does the target already have a status ailment?
- jr nz, .didntAffect
-; check if the target is immune due to types
- ld a, [de]
- cp ELECTRIC
- jr nz, .hitTest
- ld b, h
- ld c, l
- inc bc
- ld a, [bc]
- cp GROUND
- jr z, .doesntAffect
- inc bc
- ld a, [bc]
- cp GROUND
- jr z, .doesntAffect
-.hitTest
- push hl
- callab MoveHitTest
- pop hl
- ld a, [W_MOVEMISSED]
- and a
- jr nz, .didntAffect
- set PAR, [hl]
- callab QuarterSpeedDueToParalysis
- ld c, 30
- call DelayFrames
- callab PlayCurrentMoveAnimation
- ld hl, PrintMayNotAttackText
- ld b, BANK(PrintMayNotAttackText)
- jp Bankswitch
-.didntAffect
- ld c, 50
- call DelayFrames
- ld hl, PrintDidntAffectText
- ld b, BANK(PrintDidntAffectText)
- jp Bankswitch
-.doesntAffect
- ld c, 50
- call DelayFrames
- ld hl, PrintDoesntAffectText
- ld b, BANK(PrintDoesntAffectText)
- jp Bankswitch
--- a/engine/battle/15.asm
+++ /dev/null
@@ -1,372 +1,0 @@
-GainExperience: ; 5524f (15:524f)
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- ret z ; return if link battle
- call DivideExpDataByNumMonsGainingExp
- ld hl, wPartyMon1
- xor a
- ld [wWhichPokemon], a
-.partyMonLoop ; loop over each mon and add gained exp
- inc hl
- ld a, [hli]
- or [hl] ; is mon's HP 0?
- jp z, .nextMon ; if so, go to next mon
- push hl
- ld hl, wPartyGainExpFlags
- ld a, [wWhichPokemon]
- ld c, a
- ld b, $2
- predef FlagActionPredef
- ld a, c
- and a ; is mon's gain exp flag set?
- pop hl
- jp z, .nextMon ; if mon's gain exp flag not set, go to next mon
- ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1)
- add hl, de
- ld d, h
- ld e, l
- ld hl, wEnemyMonBaseStats
- ld c, $5
-.gainStatExpLoop
- ld a, [hli]
- ld b, a ; enemy mon base stat
- ld a, [de] ; stat exp
- add b ; add enemy mon base state to stat exp
- ld [de], a
- jr nc, .nextBaseStat
-; if there was a carry, increment the upper byte
- dec de
- ld a, [de]
- inc a
- jr z, .maxStatExp ; jump if the value overflowed
- ld [de], a
- inc de
- jr .nextBaseStat
-.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp
- ld a, $ff
- ld [de], a
- inc de
- ld [de], a
-.nextBaseStat
- dec c
- jr z, .asm_552a1
- inc de
- inc de
- jr .gainStatExpLoop
-.asm_552a1
- xor a
- ld [H_MULTIPLICAND], a
- ld [H_MULTIPLICAND + 1], a
- ld a, [wEnemyMonBaseExp]
- ld [H_MULTIPLICAND + 2], a
- ld a, [wEnemyMonLevel]
- ld [H_MULTIPLIER], a
- call Multiply
- ld a, 7
- ld [H_DIVISOR], a
- ld b, 4
- call Divide
- ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2)
- add hl, de
- ld b, [hl] ; party mon OTID
- inc hl
- ld a, [wPlayerID]
- cp b
- jr nz, .tradedMon
- ld b, [hl]
- ld a, [wPlayerID + 1]
- cp b
- ld a, $0
- jr z, .next
-.tradedMon
- call BoostExp ; traded mon exp boost
- ld a, $1
-.next
- ld [wcf4d], a
- ld a, [W_ISINBATTLE]
- dec a ; is it a trainer battle?
- call nz, BoostExp ; if so, boost exp
- inc hl
- inc hl
- inc hl
-; add the gained exp to the party mon's exp
- ld b, [hl]
- ld a, [H_QUOTIENT + 3]
- ld [wcf4c], a
- add b
- ld [hld], a
- ld b, [hl]
- ld a, [H_QUOTIENT + 2]
- ld [wcf4b], a
- adc b
- ld [hl], a
- jr nc, .noCarry
- dec hl
- inc [hl]
- inc hl
-.noCarry
-; calculate exp for the mon at max level, and cap the exp at that value
- inc hl
- push hl
- ld a, [wWhichPokemon]
- ld c, a
- ld b, 0
- ld hl, wPartySpecies
- add hl, bc
- ld a, [hl] ; species
- ld [wd0b5], a
- call GetMonHeader
- ld d, MAX_LEVEL
- callab CalcExperience ; get max exp
-; compare max exp with current exp
- ld a, [$ff96]
- ld b, a
- ld a, [$ff97]
- ld c, a
- ld a, [$ff98]
- ld d, a
- pop hl
- ld a, [hld]
- sub d
- ld a, [hld]
- sbc c
- ld a, [hl]
- sbc b
- jr c, .next2
-; the mon's exp is greater than the max exp, so overwrite it with the max exp
- ld a, b
- ld [hli], a
- ld a, c
- ld [hli], a
- ld a, d
- ld [hld], a
- dec hl
-.next2
- push hl
- ld a, [wWhichPokemon]
- ld hl, wPartyMonNicks
- call GetPartyMonName
- ld hl, GainedText
- call PrintText
- xor a ; party mon data
- ld [wcc49], a
- call LoadMonData
- pop hl
- ld bc, wPartyMon1Level - wPartyMon1Exp
- add hl, bc
- push hl
- callba CalcLevelFromExperience
- pop hl
- ld a, [hl] ; current level
- cp d
- jp z, .nextMon ; if level didn't change, go to next mon
- ld a, [W_CURENEMYLVL]
- push af
- push hl
- ld a, d
- ld [W_CURENEMYLVL], a
- ld [hl], a
- ld bc, wPartyMon1Species - wPartyMon1Level
- add hl, bc
- ld a, [hl] ; species
- ld [wd0b5], a
- ld [wd11e], a
- call GetMonHeader
- ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species
- add hl, bc
- push hl
- ld a, [hld]
- ld c, a
- ld b, [hl]
- push bc ; push max HP (from before levelling up)
- ld d, h
- ld e, l
- ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP
- add hl, bc
- ld b, $1 ; consider stat exp when calculating stats
- call CalcStats
- pop bc ; pop max HP (from before levelling up)
- pop hl
- ld a, [hld]
- sub c
- ld c, a
- ld a, [hl]
- sbc b
- ld b, a ; bc = difference between old max HP and new max HP after levelling
- ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
- add hl, de
-; add to the current HP the amount of max HP gained when levelling
- ld a, [hl] ; wPartyMon1HP + 1
- add c
- ld [hld], a
- ld a, [hl] ; wPartyMon1HP + 1
- adc b
- ld [hl], a ; wPartyMon1HP
- ld a, [wPlayerMonNumber]
- ld b, a
- ld a, [wWhichPokemon]
- cp b ; is the current mon in battle?
- jr nz, .printGrewLevelText
-; current mon is in battle
- ld de, wBattleMonHP
-; copy party mon HP to battle mon HP
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
-; copy other stats from party mon to battle mon
- ld bc, wPartyMon1Level - (wPartyMon1HP + 1)
- add hl, bc
- push hl
- ld de, wBattleMonLevel
- ld bc, $b ; size of stats
- call CopyData
- pop hl
- ld a, [W_PLAYERBATTSTATUS3]
- bit 3, a ; is the mon transformed?
- jr nz, .recalcStatChanges
-; the mon is not transformed, so update the unmodified stats
- ld de, wPlayerMonUnmodifiedLevel
- ld bc, $b
- call CopyData
-.recalcStatChanges
- xor a
- ld [wd11e], a
- callab CalculateModifiedStats
- callab ApplyBurnAndParalysisPenaltiesToPlayer
- callab ApplyBadgeStatBoosts
- callab DrawPlayerHUDAndHPBar
- callab PrintEmptyString
- call SaveScreenTilesToBuffer1
-.printGrewLevelText
- ld hl, GrewLevelText
- call PrintText
- xor a ; party mon data
- ld [wcc49], a
- call LoadMonData
- ld d, $1
- callab PrintStatsBox
- call WaitForTextScrollButtonPress
- call LoadScreenTilesFromBuffer1
- xor a
- ld [wcc49], a
- ld a, [wd0b5]
- ld [wd11e], a
- predef LearnMoveFromLevelUp
- ld hl, wccd3
- ld a, [wWhichPokemon]
- ld c, a
- ld b, $1
- predef FlagActionPredef
- pop hl
- pop af
- ld [W_CURENEMYLVL], a
-
-.nextMon
- ld a, [wPartyCount]
- ld b, a
- ld a, [wWhichPokemon]
- inc a
- cp b
- jr z, .done
- ld [wWhichPokemon], a
- ld bc, wPartyMon2 - wPartyMon1
- ld hl, wPartyMon1
- call AddNTimes
- jp .partyMonLoop
-.done
- ld hl, wPartyGainExpFlags
- xor a
- ld [hl], a ; clear gain exp flags
- ld a, [wPlayerMonNumber]
- ld c, a
- ld b, $1
- push bc
- predef FlagActionPredef ; set the gain exp flag for the mon that is currently out
- ld hl, wPartyFoughtCurrentEnemyFlags
- xor a
- ld [hl], a
- pop bc
- predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out
-
-; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp
-DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c)
- ld a, [wPartyGainExpFlags]
- ld b, a
- xor a
- ld c, $8
- ld d, $0
-.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags
- xor a
- srl b
- adc d
- ld d, a
- dec c
- jr nz, .countSetBitsLoop
- cp $2
- ret c ; return if only one mon is gaining exp
- ld [wd11e], a ; store number of mons gaining exp
- ld hl, wEnemyMonBaseStats
- ld c, $7
-.divideLoop
- xor a
- ld [H_DIVIDEND], a
- ld a, [hl]
- ld [H_DIVIDEND + 1], a
- ld a, [wd11e]
- ld [H_DIVISOR], a
- ld b, $2
- call Divide ; divide value by number of mons gaining exp
- ld a, [H_QUOTIENT + 3]
- ld [hli], a
- dec c
- jr nz, .divideLoop
- ret
-
-; multiplies exp by 1.5
-BoostExp: ; 5549f (15:549f)
- ld a, [H_QUOTIENT + 2]
- ld b, a
- ld a, [H_QUOTIENT + 3]
- ld c, a
- srl b
- rr c
- add c
- ld [H_QUOTIENT + 3], a
- ld a, [H_QUOTIENT + 2]
- adc b
- ld [H_QUOTIENT + 2], a
- ret
-
-GainedText: ; 554b2 (15:54b2)
- TX_FAR _GainedText
- db $08 ; asm
- ld a, [wcc5b]
- ld hl, WithExpAllText
- and a
- ret nz
- ld hl, ExpPointsText
- ld a, [wcf4d]
- and a
- ret z
- ld hl, BoostedText
- ret
-
-WithExpAllText: ; 554cb (15:54cb)
- TX_FAR _WithExpAllText
- db $08 ; asm
- ld hl, ExpPointsText
- ret
-
-BoostedText: ; 554d4 (15:54d4)
- TX_FAR _BoostedText
-
-ExpPointsText: ; 554d8 (15:54d8)
- TX_FAR _ExpPointsText
- db "@"
-
-GrewLevelText: ; 554dd (15:54dd)
- TX_FAR _GrewLevelText
- db $0b
- db "@"
--- a/engine/battle/16.asm
+++ /dev/null
@@ -1,238 +1,0 @@
-PrintBeginningBattleText: ; 58d99 (16:4d99)
- ld a, [W_ISINBATTLE] ; W_ISINBATTLE
- dec a
- jr nz, .trainerBattle
- ld a, [W_CURMAP] ; W_CURMAP
- cp POKEMONTOWER_3
- jr c, .notPokemonTower
- cp LAVENDER_HOUSE_1
- jr c, .pokemonTower
-.notPokemonTower
- ld a, [wEnemyMonSpecies2]
- call PlayCry
- ld hl, WildMonAppearedText
- ld a, [W_MOVEMISSED] ; W_MOVEMISSED
- and a
- jr z, .notFishing
- ld hl, HookedMonAttackedText
-.notFishing
- jr .wildBattle
-.trainerBattle
- call .playSFX
- ld c, $14
- call DelayFrames
- ld hl, TrainerWantsToFightText
-.wildBattle
- push hl
- callab DrawAllPokeballs
- pop hl
- call PrintText
- jr .done
-.pokemonTower
- ld b, SILPH_SCOPE
- call IsItemInBag
- ld a, [wEnemyMonSpecies2]
- ld [wcf91], a
- cp MAROWAK
- jr z, .isMarowak
- ld a, b
- and a
- jr z, .noSilphScope
- callab LoadEnemyMonData
- jr .notPokemonTower
-.noSilphScope
- ld hl, EnemyAppearedText
- call PrintText
- ld hl, GhostCantBeIDdText
- call PrintText
- jr .done
-.isMarowak
- ld a, b
- and a
- jr z, .noSilphScope
- ld hl, EnemyAppearedText
- call PrintText
- ld hl, UnveiledGhostText
- call PrintText
- callab LoadEnemyMonData
- callab MarowakAnim
- ld hl, WildMonAppearedText
- call PrintText
-
-.playSFX
- xor a
- ld [wc0f1], a
- ld a, $80
- ld [wc0f2], a
- ld a, (SFX_08_77 - SFX_Headers_08) / 3
- call PlaySound
- jp WaitForSoundToFinish
-.done
- ret
-
-WildMonAppearedText: ; 58e3b (16:4e3b)
- TX_FAR _WildMonAppearedText
- db "@"
-
-HookedMonAttackedText: ; 58e40 (16:4e40)
- TX_FAR _HookedMonAttackedText
- db "@"
-
-EnemyAppearedText: ; 58e45 (16:4e45)
- TX_FAR _EnemyAppearedText
- db "@"
-
-TrainerWantsToFightText: ; 58e4a (16:4e4a)
- TX_FAR _TrainerWantsToFightText
- db "@"
-
-UnveiledGhostText: ; 58e4f (16:4e4f)
- TX_FAR _UnveiledGhostText
- db "@"
-
-GhostCantBeIDdText: ; 58e54 (16:4e54)
- TX_FAR _GhostCantBeIDdText
- db "@"
-
-PrintSendOutMonMessage: ; 58e59 (16:4e59)
- ld hl, wEnemyMonHP
- ld a, [hli]
- or [hl]
- ld hl, GoText
- jr z, .printText
- xor a
- ld [H_MULTIPLICAND], a
- ld hl, wEnemyMonHP
- ld a, [hli]
- ld [wcce3], a
- ld [H_MULTIPLICAND + 1], a
- ld a, [hl]
- ld [wcce4], a
- ld [H_MULTIPLICAND + 2], a
- ld a, 25
- ld [H_MULTIPLIER], a
- call Multiply
- ld hl, wEnemyMonMaxHP
- ld a, [hli]
- ld b, [hl]
- srl a
- rr b
- srl a
- rr b
- ld a, b
- ld b, $4
- ld [H_DIVISOR], a ; enemy mon max HP divided by 4
- call Divide
- ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP
- ld hl, GoText ; 70% or greater
- cp 70
- jr nc, .printText
- ld hl, DoItText ; 40% - 69%
- cp 40
- jr nc, .printText
- ld hl, GetmText ; 10% - 39%
- cp 10
- jr nc, .printText
- ld hl, EnemysWeakText ; 0% - 9%
-.printText
- jp PrintText
-
-GoText: ; 58eae (16:4eae)
- TX_FAR _GoText
- db $08 ; asm
- jr PrintPlayerMon1Text
-
-DoItText: ; 58eb5 (16:4eb5)
- TX_FAR _DoItText
- db $08 ; asm
- jr PrintPlayerMon1Text
-
-GetmText: ; 58ebc (16:4ebc)
- TX_FAR _GetmText
- db $08 ; asm
- jr PrintPlayerMon1Text
-
-EnemysWeakText: ; 58ec3 (16:4ec3)
- TX_FAR _EnemysWeakText
- db $08 ; asm
-
-PrintPlayerMon1Text:
- ld hl, PlayerMon1Text
- ret
-
-PlayerMon1Text: ; 58ecc (16:4ecc)
- TX_FAR _PlayerMon1Text
- db "@"
-
-RetreatMon: ; 58ed1 (16:4ed1)
- ld hl, PlayerMon2Text
- jp PrintText
-
-PlayerMon2Text: ; 58ed7 (16:4ed7)
- TX_FAR _PlayerMon2Text
- db $08 ; asm
- push de
- push bc
- ld hl, wEnemyMonHP + 1
- ld de, wcce4
- ld b, [hl]
- dec hl
- ld a, [de]
- sub b
- ld [$ff98], a
- dec de
- ld b, [hl]
- ld a, [de]
- sbc b
- ld [$ff97], a
- ld a, $19
- ld [H_POWEROFTEN], a
- call Multiply
- ld hl, wEnemyMonMaxHP
- ld a, [hli]
- ld b, [hl]
- srl a
- rr b
- srl a
- rr b
- ld a, b
- ld b, $4
- ld [H_POWEROFTEN], a
- call Divide
- pop bc
- pop de
- ld a, [$ff98]
- ld hl, EnoughText
- and a
- ret z
- ld hl, ComeBackText
- cp $1e
- ret c
- ld hl, OKExclamationText
- cp $46
- ret c
- ld hl, GoodText
- ret
-
-EnoughText: ; 58f25 (16:4f25)
- TX_FAR _EnoughText
- db $08 ; asm
- jr PrintComeBackText
-
-OKExclamationText: ; 58f2c (16:4f2c)
- TX_FAR _OKExclamationText
- db $08 ; asm
- jr PrintComeBackText
-
-GoodText: ; 58f33 (16:4f33)
- TX_FAR _GoodText
- db $08 ; asm
- jr PrintComeBackText
-
-PrintComeBackText: ; 58f3a (16:4f3a)
- ld hl, ComeBackText
- ret
-
-ComeBackText: ; 58f3e (16:4f3e)
- TX_FAR _ComeBackText
- db "@"
--- a/engine/battle/1a.asm
+++ /dev/null
@@ -1,43 +1,0 @@
-DecrementPP: ; 68000 (1a:4000)
-; after using a move, decrement pp in battle and (if not transformed?) in party
- ld a, [de]
- cp a, STRUGGLE
- ret z ; if the pokemon is using "struggle", there's nothing to do
- ; we don't decrement PP for "struggle"
- ld hl, W_PLAYERBATTSTATUS1
- ld a, [hli] ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the
- ; W_PLAYERBATTSTATUS2 status flags later
- and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes)
- ret nz ; if any of these statuses are true, don't decrement PP
- bit UsingRage, [hl]
- ret nz ; don't decrement PP either if Pokemon is using Rage
- ld hl, wBattleMonPP ; PP of first move (in battle)
-
-; decrement PP in the battle struct
- call .DecrementPP
-
-; decrement PP in the party struct
- ld a, [W_PLAYERBATTSTATUS3]
- bit Transformed, a
- ret nz ; Return if transformed. Pokemon Red stores the "current pokemon's" PP
- ; separately from the "Pokemon in your party's" PP. This is
- ; duplication -- in all cases *other* than Pokemon with Transform.
- ; Normally, this means we have to go on and make the same
- ; modification to the "party's pokemon" PP that we made to the
- ; "current pokemon's" PP. But, if we're dealing with a Transformed
- ; Pokemon, it has separate PP for the move set that it copied from
- ; its opponent, which is *not* the same as its real PP as part of your
- ; party. So we return, and don't do that part.
-
- ld hl, wPartyMon1PP ; PP of first move (in party)
- ld a, [wPlayerMonNumber] ; which mon in party is active
- ld bc, wPartyMon2 - wPartyMon1
- call AddNTimes ; calculate address of the mon to modify
-.DecrementPP
- ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use?
- ld c, a
- ld b, 0
- add hl ,bc ; calculate the address in memory of the PP we need to decrement
- ; based on the move chosen.
- dec [hl] ; Decrement PP
- ret
--- a/engine/battle/1c.asm
+++ /dev/null
@@ -1,905 +1,0 @@
-MarowakAnim: ; 708ca (1c:48ca)
-; animate the ghost being unveiled as a Marowak
- ld a, $e4
- ld [rOBP1], a
- call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same
-; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap
- hlCoord 12, 0
- ld bc, $707
- call ClearScreenArea
- call Delay3
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon
-; replace ghost pic with Marowak in BG
- ld a, MAROWAK
- ld [wHPBarMaxHP], a
- ld a, $1
- ld [H_WHOSETURN], a
- callab Func_79793
- ; alternate between black and light grey 8 times.
- ; this makes the ghost's body appear to flash
- ld d, $80
- call FlashSprite8Times
-.fadeOutGhostLoop
- ld c, 10
- call DelayFrames
- ld a, [rOBP1]
- sla a
- sla a
- ld [rOBP1], a
- jr nz, .fadeOutGhostLoop
- call ClearSprites
- call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM
- ld b, $e4
-.fadeInMarowakLoop
- ld c, 10
- call DelayFrames
- ld a, [rOBP1]
- srl b
- rra
- srl b
- rra
- ld [rOBP1], a
- ld a, b
- and a
- jr nz, .fadeInMarowakLoop
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared
- call Delay3
- jp ClearSprites
-
-; copies a mon pic's from background VRAM to sprite VRAM and sets up OAM
-CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a)
- ld de, vFrontPic
- ld hl, vSprites
- ld bc, 7 * 7
- call CopyVideoData
- ld a, $10
- ld [W_BASECOORDY], a
- ld a, $70
- ld [W_BASECOORDX], a
- ld hl, wOAMBuffer
- ld bc, $606
- ld d, $8
-.oamLoop
- push bc
- ld a, [W_BASECOORDY]
- ld e, a
-.oamInnerLoop
- ld a, e
- add $8
- ld e, a
- ld [hli], a
- ld a, [W_BASECOORDX]
- ld [hli], a
- ld a, d
- ld [hli], a
- ld a, $10 ; use OBP1
- ld [hli], a
- inc d
- dec c
- jr nz, .oamInnerLoop
- inc d
- ld a, [W_BASECOORDX]
- add $8
- ld [W_BASECOORDX], a
- pop bc
- dec b
- jr nz, .oamLoop
- ret
-
-BattleTransition: ; 7096d (1c:496d)
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- xor a
- ld [hWY], a
- dec a
- ld [wUpdateSpritesEnabled], a
- call DelayFrame
- ld hl, wSpriteStateData1 + 2
- ld a, [H_DOWNARROWBLINKCNT2]
- ld c, a
- ld b, $0
- ld de, $10
-.loop1
- ld a, [hl]
- cp $ff
- jr z, .skip1
- inc b
-.skip1
- add hl, de
- dec c
- jr nz, .loop1
- ld hl, wOAMBuffer + $10
- ld c, $9
-.loop2
- ld a, b
- swap a
- cp l
- jr z, .skip2
- push hl
- push bc
- ld bc, $10
- xor a
- call FillMemory
- pop bc
- pop hl
-.skip2
- ld de, $10
- add hl, de
- dec c
- jr nz, .loop2
- call Delay3
- call LoadBattleTransitionTile
- ld bc, $0
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr z, .linkBattle
- call GetBattleTransitionID_WildOrTrainer
- call GetBattleTransitionID_CompareLevels
- call GetBattleTransitionID_IsDungeonMap
-.linkBattle
- ld hl, BattleTransitions
- add hl, bc
- add hl, bc
- ld a, [hli]
- ld h, [hl]
- ld l, a
- jp [hl]
-
-; the three GetBattleTransitionID functions set the first
-; three bits of c, which determines what transition animation
-; to play at the beginning of a battle
-; bit 0: set if trainer battle
-; bit 1: set if enemy is at least 3 levels higher than player
-; bit 2: set if dungeon map
-BattleTransitions: ; 709d2 (1c:49d2)
- dw BattleTransition_DoubleCircle ; %000
- dw BattleTransition_Spiral ; %001
- dw BattleTransition_Circle ; %010
- dw BattleTransition_Spiral ; %011
- dw BattleTransition_HorizontalStripes ; %100
- dw BattleTransition_Shrink ; %101
- dw BattleTransition_VerticalStripes ; %110
- dw BattleTransition_Split ; %111
-
-GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2)
- ld a, [W_CUROPPONENT]
- cp $c8
- jr nc, .trainer
- res 0, c
- ret
-.trainer
- set 0, c
- ret
-
-GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef)
- ld hl, wPartyMon1HP
-.faintedLoop
- ld a, [hli]
- or [hl]
- jr nz, .notFainted
- ld de, wPartyMon2 - (wPartyMon1 + 1)
- add hl, de
- jr .faintedLoop
-.notFainted
- ld de, wPartyMon1Level - (wPartyMon1HP + 1)
- add hl, de
- ld a, [hl]
- add $3
- ld e, a
- ld a, [W_CURENEMYLVL]
- sub e
- jr nc, .highLevelEnemy
- res 1, c
- ld a, $1
- ld [wcd47], a
- ret
-.highLevelEnemy
- set 1, c
- xor a
- ld [wcd47], a
- ret
-
-; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps,
-; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE
-; and SILPH_CO_[9-11]F as dungeon maps
-GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19)
- ld a, [W_CURMAP]
- ld e, a
- ld hl, DungeonMaps1
-.loop1
- ld a, [hli]
- cp $ff
- jr z, .noMatch1
- cp e
- jr nz, .loop1
-.match
- set 2, c
- ret
-.noMatch1
- ld hl, DungeonMaps2
-.loop2
- ld a, [hli]
- cp $ff
- jr z, .noMatch2
- ld d, a
- ld a, [hli]
- cp e
- jr c, .loop2
- ld a, e
- cp d
- jr nc, .match
-.noMatch2
- res 2, c
- ret
-
-; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
-; is equal to one of these maps
-DungeonMaps1: ; 70a3f (1c:4a3f)
- db VIRIDIAN_FOREST
- db ROCK_TUNNEL_1
- db SEAFOAM_ISLANDS_1
- db ROCK_TUNNEL_2
- db $FF
-
-; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
-; is in between or equal to each pair of maps
-DungeonMaps2: ; 70a44 (1c:4a44)
- ; all MT_MOON maps
- db MT_MOON_1
- db MT_MOON_3
-
- ; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME
- db SS_ANNE_1
- db HALL_OF_FAME
-
- ; all POKEMONTOWER maps and Lavender Town buildings
- db LAVENDER_POKECENTER
- db LAVENDER_HOUSE_2
-
- ; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps,
- ; except for SILPH_CO_1F
- db SILPH_CO_2F
- db UNKNOWN_DUNGEON_1
- db $FF
-
-LoadBattleTransitionTile: ; 70a4d (1c:4a4d)
- ld hl, vChars1 + $7f0
- ld de, BattleTransitionTile
- ld bc, (BANK(BattleTransitionTile) << 8) + $01
- jp CopyVideoData
-
-BattleTransitionTile: ; 70a59 (1c:4a59)
- INCBIN "gfx/battle_transition.2bpp"
-
-BattleTransition_BlackScreen: ; 70a69 (1c:4a69)
- ld a, $ff
- ld [rBGP], a
- ld [rOBP0], a
- ld [rOBP1], a
- ret
-
-; for non-dungeon trainer battles
-; called regardless of mon levels, but does an
-; outward spiral if enemy is at least 3 levels
-; higher than player and does an inward spiral otherwise
-BattleTransition_Spiral: ; 70a72 (1c:4a72)
- ld a, [wcd47]
- and a
- jr z, .outwardSpiral
- call BattleTransition_InwardSpiral
- jr .done
-.outwardSpiral
- hlCoord 10, 10
- ld a, $3
- ld [wd09f], a
- ld a, l
- ld [wd09b], a
- ld a, h
- ld [wd09a], a
- ld b, $78
-.loop1
- ld c, $3
-.loop2
- push bc
- call BattleTransition_OutwardSpiral_
- pop bc
- dec c
- jr nz, .loop2
- call DelayFrame
- dec b
- jr nz, .loop1
-.done
- call BattleTransition_BlackScreen
- xor a
- ld [wd09b], a
- ld [wd09a], a
- ret
-
-BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa)
- ld a, $7
- ld [wWhichTrade], a
- ld hl, wTileMap
- ld c, $11
- ld de, $14
- call BattleTransition_InwardSpiral_
- inc c
- jr .skip
-.loop
- ld de, $14
- call BattleTransition_InwardSpiral_
-.skip
- inc c
- ld de, $1
- call BattleTransition_InwardSpiral_
- dec c
- dec c
- ld de, $ffec
- call BattleTransition_InwardSpiral_
- inc c
- ld de, rIE
- call BattleTransition_InwardSpiral_
- dec c
- dec c
- ld a, c
- and a
- jr nz, .loop
- ret
-
-BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0)
- push bc
-.loop
- ld [hl], $ff
- add hl, de
- push bc
- ld a, [wWhichTrade]
- dec a
- jr nz, .skip
- call BattleTransition_TransferDelay3
- ld a, $7
-.skip
- ld [wWhichTrade], a
- pop bc
- dec c
- jr nz, .loop
- pop bc
- ret
-
-BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9)
- ld bc, $ffec
- ld de, $14
- ld a, [wd09b]
- ld l, a
- ld a, [wd09a]
- ld h, a
- ld a, [wd09f]
- cp $0
- jr z, .zero
- cp $1
- jr z, .one
- cp $2
- jr z, .two
- cp $3
- jr z, .three
-.done1
- ld [hl], $ff
-.done2_
- ld a, l
- ld [wd09b], a
- ld a, h
- ld [wd09a], a
- ret
-.zero
- dec hl
- ld a, [hl]
- cp $ff
- jr nz, .done2
- inc hl
- add hl, bc
- jr .done1
-.one
- add hl, de
- ld a, [hl]
- cp $ff
- jr nz, .done2
- add hl, bc
- dec hl
- jr .done1
-.two
- inc hl
- ld a, [hl]
- cp $ff
- jr nz, .done2
- dec hl
- add hl, de
- jr .done1
-.three
- add hl, bc
- ld a, [hl]
- cp $ff
- jr nz, .done2
- add hl, de
- inc hl
- jr .done1
-.done2
- ld [hl], $ff
- ld a, [wd09f]
- inc a
- cp $4
- jr nz, .skip
- xor a
-.skip
- ld [wd09f], a
- jr .done2_
-
-FlashScreen:
-BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d)
- ld hl, BattleTransition_FlashScreenPalettes
-.loop
- ld a, [hli]
- cp $1
- jr z, .done
- ld [rBGP], a
- ld c, $2
- call DelayFrames
- jr .loop
-.done
- dec b
- jr nz, BattleTransition_FlashScreen_
- ret
-
-BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72)
- db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4
- db $01 ; terminator
-
-; used for low level trainer dungeon battles
-BattleTransition_Shrink: ; 70b7f (1c:4b7f)
- ld c, $9
-.loop
- push bc
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- hlCoord 0, 7
- deCoord 0, 8
- ld bc, $ffd8
- call BattleTransition_CopyTiles1
- hlCoord 0, 10
- deCoord 0, 9
- ld bc, $28
- call BattleTransition_CopyTiles1
- hlCoord 8, 0
- deCoord 9, 0
- ld bc, $fffe
- call BattleTransition_CopyTiles2
- hlCoord 11, 0
- deCoord 10, 0
- ld bc, $2
- call BattleTransition_CopyTiles2
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- ld c, $6
- call DelayFrames
- pop bc
- dec c
- jr nz, .loop
- call BattleTransition_BlackScreen
- ld c, $a
- jp DelayFrames
-
-; used for high level trainer dungeon battles
-BattleTransition_Split: ; 70bca (1c:4bca)
- ld c, $9
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
-.loop
- push bc
- hlCoord 0, 16
- deCoord 0, 17
- ld bc, $ffd8
- call BattleTransition_CopyTiles1
- hlCoord 0, 1
- ld de, wTileMap
- ld bc, $28
- call BattleTransition_CopyTiles1
- hlCoord 18, 0
- deCoord 19, 0
- ld bc, $fffe
- call BattleTransition_CopyTiles2
- hlCoord 1, 0
- ld de, wTileMap
- ld bc, $2
- call BattleTransition_CopyTiles2
- call BattleTransition_TransferDelay3
- call Delay3
- pop bc
- dec c
- jr nz, .loop
- call BattleTransition_BlackScreen
- ld c, $a
- jp DelayFrames
-
-BattleTransition_CopyTiles1: ; 70c12 (1c:4c12)
- ld a, c
- ld [wWhichTrade], a
- ld a, b
- ld [wTrainerEngageDistance], a
- ld c, $8
-.loop1
- push bc
- push hl
- push de
- ld bc, $14
- call CopyData
- pop hl
- pop de
- ld a, [wWhichTrade]
- ld c, a
- ld a, [wTrainerEngageDistance]
- ld b, a
- add hl, bc
- pop bc
- dec c
- jr nz, .loop1
- ld l, e
- ld h, d
- ld a, $ff
- ld c, $14
-.loop2
- ld [hli], a
- dec c
- jr nz, .loop2
- ret
-
-BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f)
- ld a, c
- ld [wWhichTrade], a
- ld a, b
- ld [wTrainerEngageDistance], a
- ld c, $9
-.loop1
- push bc
- push hl
- push de
- ld c, $12
-.loop2
- ld a, [hl]
- ld [de], a
- ld a, e
- add $14
- jr nc, .noCarry1
- inc d
-.noCarry1
- ld e, a
- ld a, l
- add $14
- jr nc, .noCarry2
- inc h
-.noCarry2
- ld l, a
- dec c
- jr nz, .loop2
- pop hl
- pop de
- ld a, [wWhichTrade]
- ld c, a
- ld a, [wTrainerEngageDistance]
- ld b, a
- add hl, bc
- pop bc
- dec c
- jr nz, .loop1
- ld l, e
- ld h, d
- ld de, $14
- ld c, $12
-.loop3
- ld [hl], $ff
- add hl, de
- dec c
- jr nz, .loop3
- ret
-
-; used for high level wild dungeon battles
-BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e)
- ld c, $12
- ld hl, wTileMap
- deCoord 1, 17
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
-.loop
- push bc
- push hl
- push de
- push de
- call BattleTransition_VerticalStripes_
- pop hl
- call BattleTransition_VerticalStripes_
- call BattleTransition_TransferDelay3
- pop hl
- ld bc, $ffec
- add hl, bc
- ld e, l
- ld d, h
- pop hl
- ld bc, $14
- add hl, bc
- pop bc
- dec c
- jr nz, .loop
- jp BattleTransition_BlackScreen
-
-BattleTransition_VerticalStripes_: ; 70caa (1c:4caa)
- ld c, $a
-.loop
- ld [hl], $ff
- inc hl
- inc hl
- dec c
- jr nz, .loop
- ret
-
-; used for low level wild dungeon battles
-BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4)
- ld c, $14
- ld hl, wTileMap
- deCoord 19, 1
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
-.loop
- push bc
- push hl
- push de
- push de
- call BattleTransition_HorizontalStripes_
- pop hl
- call BattleTransition_HorizontalStripes_
- call BattleTransition_TransferDelay3
- pop de
- pop hl
- pop bc
- inc hl
- dec de
- dec c
- jr nz, .loop
- jp BattleTransition_BlackScreen
-
-BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8)
- ld c, $9
- ld de, $28
-.loop
- ld [hl], $ff
- add hl, de
- dec c
- jr nz, .loop
- ret
-
-; used for high level wild non-dungeon battles
-; makes one full circle around the screen
-; by animating each half circle one at a time
-BattleTransition_Circle: ; 70ce4 (1c:4ce4)
- call BattleTransition_FlashScreen
- ld bc, $000a
- ld hl, BattleTransition_HalfCircle1
- call BattleTransition_Circle_Sub1
- ld c, $a
- ld b, $1
- ld hl, BattleTransition_HalfCircle2
- call BattleTransition_Circle_Sub1
- jp BattleTransition_BlackScreen
-
-BattleTransition_FlashScreen: ; 70cfd (1c:4cfd)
- ld b, $3
- call BattleTransition_FlashScreen_
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06)
- push bc
- push hl
- ld a, b
- call BattleTransition_Circle_Sub2
- pop hl
- ld bc, $0005
- add hl, bc
- call BattleTransition_TransferDelay3
- pop bc
- dec c
- jr nz, BattleTransition_Circle_Sub1
- ret
-
-BattleTransition_TransferDelay3: ; 70d19 (1c:4d19)
- ld a, $1
- ld [H_AUTOBGTRANSFERENABLED], a
- call Delay3
- xor a
- ld [H_AUTOBGTRANSFERENABLED], a
- ret
-
-; used for low level wild non-dungeon battles
-; makes two half circles around the screen
-; by animating both half circles at the same time
-BattleTransition_DoubleCircle: ; 70d24 (1c:4d24)
- call BattleTransition_FlashScreen
- ld c, $a
- ld hl, BattleTransition_HalfCircle1
- ld de, BattleTransition_HalfCircle2
-.loop
- push bc
- push hl
- push de
- push de
- xor a
- call BattleTransition_Circle_Sub2
- pop hl
- ld a, $1
- call BattleTransition_Circle_Sub2
- pop hl
- ld bc, $5
- add hl, bc
- ld e, l
- ld d, h
- pop hl
- add hl, bc
- call BattleTransition_TransferDelay3
- pop bc
- dec c
- jr nz, .loop
- jp BattleTransition_BlackScreen
-
-BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50)
- ld [wWhichTrade], a
- ld a, [hli]
- ld [wTrainerEngageDistance], a
- ld a, [hli]
- ld e, a
- ld a, [hli]
- ld d, a
- ld a, [hli]
- ld h, [hl]
- ld l, a
- jp BattleTransition_Circle_Sub3
-
-BattleTransition_HalfCircle1: ; 70d61 (1c:4d61)
- db $01
- dw BattleTransition_CircleData1
- dwCoord 18, 6
-
- db $01
- dw BattleTransition_CircleData2
- dwCoord 19, 3
-
- db $01
- dw BattleTransition_CircleData3
- dwCoord 18, 0
-
- db $01
- dw BattleTransition_CircleData4
- dwCoord 14, 0
-
- db $01
- dw BattleTransition_CircleData5
- dwCoord 10, 0
-
- db $00
- dw BattleTransition_CircleData5
- dwCoord 9, 0
-
- db $00
- dw BattleTransition_CircleData4
- dwCoord 5, 0
-
- db $00
- dw BattleTransition_CircleData3
- dwCoord 1, 0
-
- db $00
- dw BattleTransition_CircleData2
- dwCoord 0, 3
-
- db $00
- dw BattleTransition_CircleData1
- dwCoord 1, 6
-
-BattleTransition_HalfCircle2: ; 70d93 (1c:4d93)
- db $00
- dw BattleTransition_CircleData1
- dwCoord 1, 11
-
- db $00
- dw BattleTransition_CircleData2
- dwCoord 0, 14
-
- db $00
- dw BattleTransition_CircleData3
- dwCoord 1, 17
-
- db $00
- dw BattleTransition_CircleData4
- dwCoord 5, 17
-
- db $00
- dw BattleTransition_CircleData5
- dwCoord 9, 17
-
- db $01
- dw BattleTransition_CircleData5
- dwCoord 10, 17
-
- db $01
- dw BattleTransition_CircleData4
- dwCoord 14, 17
-
- db $01
- dw BattleTransition_CircleData3
- dwCoord 18, 17
-
- db $01
- dw BattleTransition_CircleData2
- dwCoord 19, 14
-
- db $01
- dw BattleTransition_CircleData1
- dwCoord 18, 11
-
-BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5)
- push hl
- ld a, [de]
- ld c, a
- inc de
-.loop1
- ld [hl], $ff
- ld a, [wTrainerEngageDistance]
- and a
- jr z, .skip1
- inc hl
- jr .skip2
-.skip1
- dec hl
-.skip2
- dec c
- jr nz, .loop1
- pop hl
- ld a, [wWhichTrade]
- and a
- ld bc, $14
- jr z, .skip3
- ld bc, $ffec
-.skip3
- add hl, bc
- ld a, [de]
- inc de
- cp $ff
- ret z
- and a
- jr z, BattleTransition_Circle_Sub3
- ld c, a
-.loop2
- ld a, [wTrainerEngageDistance]
- and a
- jr z, .skip4
- dec hl
- jr .skip5
-.skip4
- inc hl
-.skip5
- dec c
- jr nz, .loop2
- jr BattleTransition_Circle_Sub3
-
-BattleTransition_CircleData1: ; 70dfe (1c:4dfe)
- db $02,$03,$05,$04,$09,$FF
-
-BattleTransition_CircleData2: ; 70e04 (1c:4e04)
- db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF
-
-BattleTransition_CircleData3: ; 70e0e (1c:4e0e)
- db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF
-
-BattleTransition_CircleData4: ; 70e20 (1c:4e20)
- db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF
-
-BattleTransition_CircleData5: ; 70e2e (1c:4e2e)
- db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF
--- a/engine/battle/4.asm
+++ /dev/null
@@ -1,77 +1,0 @@
-; returns whether the player is one tile outside the map in Z
-IsPlayerJustOutsideMap: ; 128d8 (4:68d8)
- ld a, [W_YCOORD]
- ld b, a
- ld a, [W_CURMAPHEIGHT]
- call .compareCoordWithMapDimension
- ret z
- ld a, [W_XCOORD]
- ld b, a
- ld a, [W_CURMAPWIDTH]
-.compareCoordWithMapDimension
- add a
- cp b
- ret z
- inc b
- ret
-
-DrawHP: ; 128ef (4:68ef)
- call GetPredefRegisters
- ld a, $1
- jr DrawHP_
-
-DrawHP2: ; 128f6 (4:68f6)
- call GetPredefRegisters
- ld a, $2
-
-DrawHP_: ; 128fb (4:68fb)
- ld [wHPBarType], a
- push hl
- ld a, [wLoadedMonHP]
- ld b, a
- ld a, [wLoadedMonHP + 1]
- ld c, a
- or b
- jr nz, .nonzeroHP
- xor a
- ld c, a
- ld e, a
- ld a, $6
- ld d, a
- jp .drawHPBarAndPrintFraction
-.nonzeroHP
- ld a, [wLoadedMonMaxHP]
- ld d, a
- ld a, [wLoadedMonMaxHP + 1]
- ld e, a
- predef HPBarLength
- ld a, $6
- ld d, a
- ld c, a
-.drawHPBarAndPrintFraction
- pop hl
- push de
- push hl
- push hl
- call DrawHPBar
- pop hl
- ld a, [hFlags_0xFFF6]
- bit 0, a
- jr z, .printFractionBelowBar
- ld bc, $9 ; right of bar
- jr .printFraction
-.printFractionBelowBar
- ld bc, SCREEN_WIDTH + 1 ; below bar
-.printFraction
- add hl, bc
- ld de, wLoadedMonHP
- ld bc, $203
- call PrintNumber
- ld a, "/"
- ld [hli], a
- ld de, wLoadedMonMaxHP
- ld bc, $203
- call PrintNumber
- pop hl
- pop de
- ret
--- a/engine/battle/4_2.asm
+++ /dev/null
@@ -1,413 +1,0 @@
-EndOfBattle: ; 137aa (4:77aa)
- ld a, [wLinkState]
- cp LINK_STATE_BATTLING
- jr nz, .notLinkBattle
-; link battle
- ld a, [wEnemyMonPartyPos]
- ld hl, wEnemyMon1Status
- ld bc, wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld a, [wEnemyMonStatus]
- ld [hl], a
- call ClearScreen
- callab DisplayLinkBattleVersusTextBox
- ld a, [wBattleResult]
- cp $1
- ld de, YouWinText
- jr c, .placeWinOrLoseString
- ld de, YouLoseText
- jr z, .placeWinOrLoseString
- ld de, DrawText
-.placeWinOrLoseString
- hlCoord 6, 8
- call PlaceString
- ld c, $c8
- call DelayFrames
- jr .evolution
-.notLinkBattle
- ld a, [wBattleResult]
- and a
- jr nz, .resetVariables
- ld hl, wTotalPayDayMoney
- ld a, [hli]
- or [hl]
- inc hl
- or [hl]
- jr z, .evolution ; if pay day money is 0, jump
- ld de, wPlayerMoney + 2
- ld c, $3
- predef AddBCDPredef
- ld hl, PickUpPayDayMoneyText
- call PrintText
-.evolution
- xor a
- ld [wccd4], a
- predef EvolutionAfterBattle
-.resetVariables
- xor a
- ld [wLowHealthAlarm], a ;disable low health alarm
- ld [wc02a], a
- ld [W_ISINBATTLE], a
- ld [W_BATTLETYPE], a
- ld [W_MOVEMISSED], a
- ld [W_CUROPPONENT], a
- ld [wd11f], a
- ld [wNumRunAttempts], a
- ld [wEscapedFromBattle], a
- ld hl, wcc2b
- ld [hli], a
- ld [hli], a
- ld [hli], a
- ld [hl], a
- ld [wListScrollOffset], a
- ld hl, wPlayerStatsToDouble
- ld b, $18
-.loop
- ld [hli], a
- dec b
- jr nz, .loop
- ld hl, wd72c
- set 0, [hl]
- call WaitForSoundToFinish
- call GBPalWhiteOut
- ld a, $ff
- ld [wDestinationWarpID], a
- ret
-
-YouWinText: ; 13853 (4:7853)
- db "YOU WIN@"
-
-YouLoseText: ; 1385b (4:785b)
- db "YOU LOSE@"
-
-DrawText: ; 13864 (4:7864)
- db " DRAW@"
-
-PickUpPayDayMoneyText: ; 1386b (4:786b)
- TX_FAR _PickUpPayDayMoneyText
- db "@"
-
-; try to initiate a wild pokemon encounter
-; returns success in Z
-TryDoWildEncounter: ; 13870 (4:7870)
- ld a, [wNPCMovementScriptPointerTableNum]
- and a
- ret nz
- ld a, [wd736]
- and a
- ret nz
- callab IsPlayerStandingOnDoorTileOrWarpTile
- jr nc, .notStandingOnDoorOrWarpTile
-.CantEncounter
- ld a, $1
- and a
- ret
-.notStandingOnDoorOrWarpTile
- callab IsPlayerJustOutsideMap
- jr z, .CantEncounter
- ld a, [wRepelRemainingSteps]
- and a
- jr z, .asm_1389e
- dec a
- jr z, .lastRepelStep
- ld [wRepelRemainingSteps], a
-.asm_1389e
-; determine if wild pok�mon can appear in the half-block we�re standing in
-; is the bottom right tile (9,9) of the half-block we're standing in a grass/water tile?
- hlCoord 9, 9
- ld c, [hl]
- ld a, [W_GRASSTILE]
- cp c
- ld a, [W_GRASSRATE]
- jr z, .CanEncounter
- ld a, $14 ; in all tilesets with a water tile, this is its id
- cp c
- ld a, [W_WATERRATE]
- jr z, .CanEncounter
-; even if not in grass/water, standing anywhere we can encounter pok�mon
-; so long as the map is �indoor� and has wild pok�mon defined.
-; �as long as it�s not Viridian Forest or Safari Zone.
- ld a, [W_CURMAP]
- cp REDS_HOUSE_1F ; is this an indoor map?
- jr c, .CantEncounter2
- ld a, [W_CURMAPTILESET]
- cp FOREST ; Viridian Forest/Safari Zone
- jr z, .CantEncounter2
- ld a, [W_GRASSRATE]
-.CanEncounter
-; compare encounter chance with a random number to determine if there will be an encounter
- ld b, a
- ld a, [hRandomAdd]
- cp b
- jr nc, .CantEncounter2
- ld a, [hRandomSub]
- ld b, a
- ld hl, WildMonEncounterSlotChances
-.determineEncounterSlot
- ld a, [hli]
- cp b
- jr nc, .gotEncounterSlot
- inc hl
- jr .determineEncounterSlot
-.gotEncounterSlot
-; determine which wild pok�mon (grass or water) can appear in the half-block we�re standing in
- ld c, [hl]
- ld hl, W_GRASSMONS
- aCoord 8, 9
- cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile?
- jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default
- ld hl, W_WATERMONS
-; since the bottom right tile of a "left shore" half-block is $14 but the bottom left tile is not,
-; "left shore" half-blocks (such as the one in the east coast of Cinnabar) load grass encounters.
-.gotWildEncounterType
- ld b, $0
- add hl, bc
- ld a, [hli]
- ld [W_CURENEMYLVL], a
- ld a, [hl]
- ld [wcf91], a
- ld [wEnemyMonSpecies2], a
- ld a, [wRepelRemainingSteps]
- and a
- jr z, .willEncounter
- ld a, [wPartyMon1Level]
- ld b, a
- ld a, [W_CURENEMYLVL]
- cp b
- jr c, .CantEncounter2 ; repel prevents encounters if the leading party mon's level is higher than the wild mon
- jr .willEncounter
-.lastRepelStep
- ld [wRepelRemainingSteps], a
- ld a, $d2
- ld [H_DOWNARROWBLINKCNT2], a
- call EnableAutoTextBoxDrawing
- call DisplayTextID
-.CantEncounter2
- ld a, $1
- and a
- ret
-.willEncounter
- xor a
- ret
-
-WildMonEncounterSlotChances: ; 13918 (4:7918)
-; There are 10 slots for wild pokemon, and this is the table that defines how common each of
-; those 10 slots is. A random number is generated and then the first byte of each pair in this
-; table is compared against that random number. If the random number is less than or equal
-; to the first byte, then that slot is chosen. The second byte is double the slot number.
- db $32, $00 ; 51/256 = 19.9% chance of slot 0
- db $65, $02 ; 51/256 = 19.9% chance of slot 1
- db $8C, $04 ; 39/256 = 15.2% chance of slot 2
- db $A5, $06 ; 25/256 = 9.8% chance of slot 3
- db $BE, $08 ; 25/256 = 9.8% chance of slot 4
- db $D7, $0A ; 25/256 = 9.8% chance of slot 5
- db $E4, $0C ; 13/256 = 5.1% chance of slot 6
- db $F1, $0E ; 13/256 = 5.1% chance of slot 7
- db $FC, $10 ; 11/256 = 4.3% chance of slot 8
- db $FF, $12 ; 3/256 = 1.2% chance of slot 9
-
-RecoilEffect_: ; 1392c (4:792c)
- ld a, [H_WHOSETURN]
- and a
- ld a, [W_PLAYERMOVENUM]
- ld hl, wBattleMonMaxHP
- jr z, .asm_1393d
- ld a, [W_ENEMYMOVENUM]
- ld hl, wEnemyMonMaxHP
-.asm_1393d
- ld d, a
- ld a, [W_DAMAGE]
- ld b, a
- ld a, [W_DAMAGE + 1]
- ld c, a
- srl b
- rr c
- ld a, d
- cp STRUGGLE
- jr z, .asm_13953
- srl b
- rr c
-.asm_13953
- ld a, b
- or c
- jr nz, .asm_13958
- inc c
-.asm_13958
- ld a, [hli]
- ld [wHPBarMaxHP+1], a
- ld a, [hl]
- ld [wHPBarMaxHP], a
- push bc
- ld bc, $fff2
- add hl, bc
- pop bc
- ld a, [hl]
- 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, .asm_13982
- xor a
- ld [hli], a
- ld [hl], a
- ld hl, wHPBarNewHP
- ld [hli], a
- ld [hl], a
-.asm_13982
- hlCoord 10, 9
- ld a, [H_WHOSETURN]
- and a
- ld a, $1
- jr z, .asm_13990
- hlCoord 2, 2
- xor a
-.asm_13990
- ld [wHPBarType], a
- predef UpdateHPBar2
- ld hl, HitWithRecoilText
- jp PrintText
-HitWithRecoilText: ; 1399e (4:799e)
- TX_FAR _HitWithRecoilText
- db "@"
-
-ConversionEffect_: ; 139a3 (4:79a3)
- ld hl, wEnemyMonType1
- ld de, wBattleMonType1
- ld a, [H_WHOSETURN]
- and a
- ld a, [W_ENEMYBATTSTATUS1]
- jr z, .asm_139b8
- push hl
- ld h, d
- ld l, e
- pop de
- ld a, [W_PLAYERBATTSTATUS1]
-.asm_139b8
- bit Invulnerable, a ; is mon immune to typical attacks (dig/fly)
- jr nz, PrintButItFailedText
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hl]
- ld [de], a
- ld hl, PlayCurrentMoveAnimation
- call CallBankF
- ld hl, ConvertedTypeText
- jp PrintText
-
-ConvertedTypeText: ; 139cd (4:79cd)
- TX_FAR _ConvertedTypeText
- db "@"
-
-PrintButItFailedText: ; 139d2 (4:79d2)
- ld hl, PrintButItFailedText_
-CallBankF: ; 139d5 (4:79d5)
- ld b, BANK(PrintButItFailedText_)
- jp Bankswitch
-
-HazeEffect_: ; 139da (4:79da)
- ld a, $7
- ld hl, wPlayerMonAttackMod
- call ResetStatMods
- ld hl, wEnemyMonAttackMod
- call ResetStatMods
- ld hl, wPlayerMonUnmodifiedAttack
- ld de, wBattleMonAttack
- call ResetStats
- ld hl, wEnemyMonUnmodifiedAttack
- ld de, wEnemyMonAttack
- call ResetStats
- ld hl, wEnemyMonStatus
- ld de, wEnemySelectedMove
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_13a09
- ld hl, wBattleMonStatus
- dec de
-
-.asm_13a09
- ld a, [hl]
- ld [hl], $0
- and $27
- jr z, .asm_13a13
- ld a, $ff
- ld [de], a
-
-.asm_13a13
- xor a
- ld [W_PLAYERDISABLEDMOVE], a
- ld [W_ENEMYDISABLEDMOVE], a
- ld hl, wccee
- ld [hli], a
- ld [hl], a
- ld hl, W_PLAYERBATTSTATUS1
- call CureStatuses
- ld hl, W_ENEMYBATTSTATUS1
- call CureStatuses
- ld hl, PlayCurrentMoveAnimation
- call CallBankF
- ld hl, StatusChangesEliminatedText
- jp PrintText
-
-CureStatuses: ; 13a37 (4:7a37)
- res Confused, [hl]
- inc hl ; BATTSTATUS2
- ld a, [hl]
- and (1 << UsingRage) | (1 << NeedsToRecharge) | (1 << HasSubstituteUp) | (1 << 3) ; clear all but these from BATTSTATUS2
- ld [hli], a ; BATTSTATUS3
- ld a, [hl]
- and %11110000 | (1 << Transformed) ; clear Bad Poison, Reflect and Light Screen statuses
- ld [hl], a
- ret
-
-ResetStatMods: ; 13a43 (4:7a43)
- ld b, $8
-.loop
- ld [hli], a
- dec b
- jr nz, .loop
- ret
-
-ResetStats: ; 13a4a (4:7a4a)
- ld b, $8
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- dec b
- jr nz, .loop
- ret
-
-StatusChangesEliminatedText: ; 13a53 (4:7a53)
- TX_FAR _StatusChangesEliminatedText
- db "@"
-
-GetTrainerName_: ; 13a58 (4:7a58)
- ld hl, W_GRASSRATE
- ld a, [wLinkState]
- and a
- jr nz, .rival
- ld hl, W_RIVALNAME
- ld a, [W_TRAINERCLASS]
- cp SONY1
- jr z, .rival
- cp SONY2
- jr z, .rival
- cp SONY3
- jr z, .rival
- ld [wd0b5], a
- ld a, TRAINER_NAME
- ld [wNameListType], a
- ld a, BANK(TrainerNames)
- ld [wPredefBank], a
- call GetName
- ld hl, wcd6d
-.rival
- ld de, W_TRAINERNAME
- ld bc, $d
- jp CopyData
--- a/engine/battle/5.asm
+++ /dev/null
@@ -1,77 +1,0 @@
-SubstituteEffectHandler: ; 17dad (5:7dad)
- ld c, 50
- call DelayFrames
- ld hl, wBattleMonMaxHP
- ld de, wPlayerSubstituteHP
- ld bc, W_PLAYERBATTSTATUS2
- ld a, [H_WHOSETURN]
- and a
- jr z, .notEnemy
- ld hl, wEnemyMonMaxHP
- ld de, wEnemySubstituteHP
- ld bc, W_ENEMYBATTSTATUS2
-.notEnemy
- ld a, [bc] ;load flags
- bit HasSubstituteUp, a ;user already has substitute?
- jr nz, .alreadyHasSubstitute ;skip this code if so
- ;user doesn't have a substitute [yet]
- push bc
- ld a, [hli] ;load max hp
- ld b, [hl]
- srl a ;max hp / 4, [quarter health to remove from user]
- rr b
- srl a
- rr b
- push de
- ld de, wBattleMonHP - wBattleMonMaxHP
- add hl, de ; point hl to current HP
- pop de
- ld a, b
- ld [de], a ;save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has]
- ld a, [hld] ;load current hp
- sub b ;subtract [max hp / 4]
- ld d, a ;save low byte result in D
- ld a, [hl]
- sbc a, 0 ;borrow from high byte if needed
- pop bc
- jr c, .notEnoughHP ;underflow means user would be left with negative health
- ;bug: note since it only brances on carry, it will possibly leave user with 0HP
-.userHasZeroOrMoreHP
- ldi [hl], a ;store high byte HP
- ld [hl], d ;store low byte HP
- ld h, b
- ld l, c
- set HasSubstituteUp, [hl] ;set bit 4 of flags, user now has substitute
- ld a, [W_OPTIONS] ;load options
- bit 7, a ;battle animation is enabled?
- ld hl, PlayCurrentMoveAnimation ;animation enabled: 0F:7BA8
- ld b, BANK(PlayCurrentMoveAnimation)
- jr z, .animationEnabled
- ld hl, AnimationSubstitute ;animation disabled: 1E:56E0
- ld b, BANK(AnimationSubstitute)
-.animationEnabled
- call Bankswitch ;jump to routine depending on animation setting
- ld hl, SubstituteText
- call PrintText
- ld hl, DrawHUDsAndHPBars
- ld b, BANK(DrawHUDsAndHPBars)
- jp Bankswitch
-.alreadyHasSubstitute
- ld hl, HasSubstituteText
- jr .printText
-.notEnoughHP
- ld hl, TooWeakSubstituteText
-.printText
- jp PrintText
-
-SubstituteText: ; 17e1d (5:7e1d)
- TX_FAR _SubstituteText
- db "@"
-
-HasSubstituteText: ; 17e22 (5:7e22)
- TX_FAR _HasSubstituteText
- db "@"
-
-TooWeakSubstituteText: ; 17e27 (5:7e27)
- TX_FAR _TooWeakSubstituteText
- db "@"
--- a/engine/battle/9.asm
+++ /dev/null
@@ -1,190 +1,0 @@
-; [wd0b5] = pokemon ID
-; hl = dest addr
-PrintMonType: ; 27d6b (9:7d6b)
- call GetPredefRegisters
- push hl
- call GetMonHeader
- pop hl
- push hl
- ld a, [W_MONHTYPE1]
- call PrintType
- ld a, [W_MONHTYPE1]
- ld b, a
- ld a, [W_MONHTYPE2]
- cp b
- pop hl
- jr z, EraseType2Text
- ld bc, SCREEN_WIDTH * 2
- add hl, bc
-
-; a = type
-; hl = dest addr
-PrintType: ; 27d89 (9:7d89)
- push hl
- jr PrintType_
-
-; erase "TYPE2/" if the mon only has 1 type
-EraseType2Text: ; 27d8c (9:7d8c)
- ld a, " "
- ld bc, $13
- add hl, bc
- ld bc, $6
- jp FillMemory
-
-PrintMoveType: ; 27d98 (9:7d98)
- call GetPredefRegisters
- push hl
- ld a, [W_PLAYERMOVETYPE]
-; fall through
-
-PrintType_: ; 27d9f (9:7d9f)
- add a
- ld hl, TypeNames
- ld e, a
- ld d, $0
- add hl, de
- ld a, [hli]
- ld e, a
- ld d, [hl]
- pop hl
- jp PlaceString
-
-INCLUDE "text/type_names.asm"
-
-SaveTrainerName: ; 27e4a (9:7e4a)
- ld hl,TrainerNamePointers
- ld a,[W_TRAINERCLASS]
- dec a
- ld c,a
- ld b,0
- add hl,bc
- add hl,bc
- ld a,[hli]
- ld h,[hl]
- ld l,a
- ld de,wcd6d
-.CopyCharacter
- ld a,[hli]
- ld [de],a
- inc de
- cp "@"
- jr nz,.CopyCharacter
- ret
-
-TrainerNamePointers: ; 27e64 (9:7e64)
-; what is the point of these?
- dw YoungsterName
- dw BugCatcherName
- dw LassName
- dw W_TRAINERNAME
- dw JrTrainerMName
- dw JrTrainerFName
- dw PokemaniacName
- dw SuperNerdName
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw BurglarName
- dw EngineerName
- dw JugglerXName
- dw W_TRAINERNAME
- dw SwimmerName
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw BeautyName
- dw W_TRAINERNAME
- dw RockerName
- dw JugglerName
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw BlackbeltName
- dw W_TRAINERNAME
- dw ProfOakName
- dw ChiefName
- dw ScientistName
- dw W_TRAINERNAME
- dw RocketName
- dw CooltrainerMName
- dw CooltrainerFName
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
- dw W_TRAINERNAME
-
-YoungsterName: ; 27ec2 (9:7ec2)
- db "YOUNGSTER@"
-BugCatcherName: ; 27ecc (9:7ecc)
- db "BUG CATCHER@"
-LassName: ; 27ed8 (9:7ed8)
- db "LASS@"
-JrTrainerMName: ; 27edd (9:7edd)
- db "JR.TRAINER♂@"
-JrTrainerFName: ; 27ee9 (9:7ee9)
- db "JR.TRAINER♀@"
-PokemaniacName: ; 27ef5 (9:7ef5)
- db "POKéMANIAC@"
-SuperNerdName: ; 27f00 (9:7f00)
- db "SUPER NERD@"
-BurglarName: ; 27f0b (9:7f0b)
- db "BURGLAR@"
-EngineerName: ; 27f13 (9:7f13)
- db "ENGINEER@"
-JugglerXName: ; 27f1c (9:7f1c)
- db "JUGGLER@"
-SwimmerName: ; 27f24 (9:7f24)
- db "SWIMMER@"
-BeautyName: ; 27f2c (9:7f2c)
- db "BEAUTY@"
-RockerName: ; 27f33 (9:7f33)
- db "ROCKER@"
-JugglerName: ; 27f3a (9:7f3a)
- db "JUGGLER@"
-BlackbeltName: ; 27f42 (9:7f42)
- db "BLACKBELT@"
-ProfOakName: ; 27f4c (9:7f4c)
- db "PROF.OAK@"
-ChiefName: ; 27f55 (9:7f55)
- db "CHIEF@"
-ScientistName: ; 27f5b (9:7f5b)
- db "SCIENTIST@"
-RocketName: ; 27f65 (9:7f65)
- db "ROCKET@"
-CooltrainerMName: ; 27f6c (9:7f6c)
- db "COOLTRAINER♂@"
-CooltrainerFName: ; 27f79 (9:7f79)
- db "COOLTRAINER♀@"
-
-FocusEnergyEffect_: ; 27f86 (9:7f86)
- ld hl, W_PLAYERBATTSTATUS2
- ld a, [H_WHOSETURN]
- and a
- jr z, .notEnemy
- ld hl, W_ENEMYBATTSTATUS2
-.notEnemy
- bit GettingPumped, [hl] ; is mon already using focus energy?
- jr nz, .alreadyUsing
- set GettingPumped, [hl] ; mon is now using focus energy
- callab PlayCurrentMoveAnimation
- ld hl, GettingPumpedText
- jp PrintText
-.alreadyUsing
- ld c, $32
- call DelayFrames
- ld hl, PrintButItFailedText_
- ld b, BANK(PrintButItFailedText_)
- jp Bankswitch
-
-GettingPumpedText: ; 27fb3 (9:7fb3)
- db $0a
- TX_FAR _GettingPumpedText
- db "@"
--- a/engine/battle/a.asm
+++ /dev/null
@@ -1,39 +1,0 @@
-LeechSeedEffect_: ; 2bea9 (a:7ea9)
- callab MoveHitTest
- ld a, [W_MOVEMISSED] ; W_MOVEMISSED
- and a
- jr nz, .asm_2bee7
- ld hl, W_ENEMYBATTSTATUS2 ; W_ENEMYBATTSTATUS2
- ld de, wEnemyMonType1 ; wcfea (aliases: wEnemyMonType)
- ld a, [H_WHOSETURN] ; $fff3
- and a
- jr z, .asm_2bec8
- ld hl, W_PLAYERBATTSTATUS2 ; W_PLAYERBATTSTATUS2
- ld de, wBattleMonType1 ; wd019 (aliases: wBattleMonType)
-.asm_2bec8
- ld a, [de]
- cp GRASS
- jr z, .asm_2bee7
- inc de
- ld a, [de]
- cp GRASS
- jr z, .asm_2bee7
- bit Seeded, [hl]
- jr nz, .asm_2bee7
- set Seeded, [hl]
- callab PlayCurrentMoveAnimation
- ld hl, WasSeededText ; $7ef2
- jp PrintText
-.asm_2bee7
- ld c, $32
- call DelayFrames
- ld hl, EvadedAttackText ; $7ef7
- jp PrintText
-
-WasSeededText: ; 2bef2 (a:7ef2)
- TX_FAR _WasSeededText
- db "@"
-
-EvadedAttackText: ; 2bef7 (a:7ef7)
- TX_FAR _EvadedAttackText
- db "@"
--- a/engine/battle/animations.asm
+++ b/engine/battle/animations.asm
@@ -407,7 +407,7 @@
ld c,30
call DelayFrames
.next4
- call Func_78dbd ; reload pic and flash the pic in and out (to show damage)
+ call PlayApplyingAttackAnimation ; shake the screen or flash the pic in and out (to show damage)
.AnimationFinished
call WaitForSoundToFinish
xor a
@@ -445,8 +445,10 @@
ld [W_ANIMATIONID],a
ret
-Func_78dbd: ; 78dbd (1e:4dbd)
- ld a,[wcc5b]
+PlayApplyingAttackAnimation: ; 78dbd (1e:4dbd)
+; Generic animation that shows after the move's individual animation
+; Different animation depending on whether the move has an additional effect and on whose turn it is
+ ld a,[wAnimationType]
and a
ret z
dec a
@@ -453,7 +455,7 @@
add a
ld c,a
ld b,0
- ld hl,PointerTable_78dcf
+ ld hl,AnimationTypePointerTable
add hl,bc
ld a,[hli]
ld h,[hl]
@@ -460,41 +462,41 @@
ld l,a
jp [hl]
-PointerTable_78dcf: ; 78dcf (1e:4dcf)
- dw Func_78ddb
- dw Func_78de3
- dw Func_78deb
- dw Func_78df0
- dw Func_78df6
- dw Func_78dfe
+AnimationTypePointerTable: ; 78dcf (1e:4dcf)
+ dw ShakeScreenVertically ; enemy mon has used a damaging move without a side effect
+ dw ShakeScreenHorizontallyHeavy ; enemy mon has used a damaging move with a side effect
+ dw ShakeScreenHorizontallySlow ; enemy mon has used a non-damaging move
+ dw BlinkEnemyMonSprite ; player mon has used a damaging move without a side effect
+ dw ShakeScreenHorizontallyLight ; player mon has used a damaging move with a side effect
+ dw ShakeScreenHorizontallySlow2 ; player mon has used a non-damaging move
-Func_78ddb: ; 78ddb (1e:4ddb)
- call Func_79e6a
+ShakeScreenVertically: ; 78ddb (1e:4ddb)
+ call PlayApplyingAttackSound
ld b, $8
- jp Func_79209
+ jp AnimationShakeScreenVertically
-Func_78de3: ; 78de3 (1e:4de3)
- call Func_79e6a
+ShakeScreenHorizontallyHeavy: ; 78de3 (1e:4de3)
+ call PlayApplyingAttackSound
ld b, $8
- jp Func_79210
+ jp AnimationShakeScreenHorizontallyFast
-Func_78deb: ; 78deb (1e:4deb)
+ShakeScreenHorizontallySlow: ; 78deb (1e:4deb)
ld bc, $602
- jr Func_78e01
+ jr AnimationShakeScreenHorizontallySlow
-Func_78df0: ; 78df0 (1e:4df0)
- call Func_79e6a
+BlinkEnemyMonSprite: ; 78df0 (1e:4df0)
+ call PlayApplyingAttackSound
jp AnimationBlinkEnemyMon
-Func_78df6: ; 78df6 (1e:4df6)
- call Func_79e6a
+ShakeScreenHorizontallyLight: ; 78df6 (1e:4df6)
+ call PlayApplyingAttackSound
ld b, $2
- jp Func_79210
+ jp AnimationShakeScreenHorizontallyFast
-Func_78dfe: ; 78dfe (1e:4dfe)
+ShakeScreenHorizontallySlow2: ; 78dfe (1e:4dfe)
ld bc, $302
-Func_78e01: ; 78e01 (1e:4e01)
+AnimationShakeScreenHorizontallySlow: ; 78e01 (1e:4e01)
push bc
push bc
.asm_78e03
@@ -516,7 +518,7 @@
jr nz, .asm_78e11
pop bc
dec c
- jr nz, Func_78e01
+ jr nz, AnimationShakeScreenHorizontallySlow
ret
Func_78e23: ; 78e23 (1e:4e23)
@@ -1225,7 +1227,7 @@
ld b, $5
-Func_79209: ; 79209 (1e:5209)
+AnimationShakeScreenVertically: ; 79209 (1e:5209)
predef_jump Func_480ff
AnimationShakeScreen: ; 7920e (1e:520e)
@@ -1232,7 +1234,7 @@
; Shakes the screen for a while. Used in Earthquake/Fissure/etc. animations.
ld b, $8
-Func_79210: ; 79210 (1e:5210)
+AnimationShakeScreenHorizontallyFast: ; 79210 (1e:5210)
predef_jump Func_48125
AnimationWaterDropletsEverywhere: ; 79215 (1e:5215)
@@ -2929,9 +2931,11 @@
ld [W_ANIMATIONID],a
jp PlayAnimation
-Func_79e6a: ; 79e6a (1e:5e6a)
+PlayApplyingAttackSound: ; 79e6a (1e:5e6a)
+; play a different sound depending if move is not very effective, neutral, or super-effective
+; don't play any sound at all if move is ineffective
call WaitForSoundToFinish
- ld a, [wd05b]
+ ld a, [wDamageMultipliers]
and $7f
ret z
cp $a
--- a/engine/battle/b.asm
+++ /dev/null
@@ -1,18 +1,0 @@
-DisplayEffectiveness: ; 2fb7b (b:7b7b)
- ld a, [wd05b]
- and a, $7F
- cp a, $0A
- ret z
- ld hl, SuperEffectiveText
- jr nc, .done
- ld hl, NotVeryEffectiveText
-.done
- jp PrintText
-
-SuperEffectiveText: ; 2fb8e (b:7b8e)
- TX_FAR _SuperEffectiveText
- db "@"
-
-NotVeryEffectiveText: ; 2fb93 (b:7b93)
- TX_FAR _NotVeryEffectiveText
- db "@"
--- a/engine/battle/b_2.asm
+++ /dev/null
@@ -1,129 +1,0 @@
-; scales both uncompressed sprite chunks by two in every dimension (creating 2x2 output pixels per input pixel)
-; assumes that input sprite chunks are 4x4 tiles, and the rightmost and bottommost 4 pixels will be ignored
-; resulting in a 7*7 tile output sprite chunk
-ScaleSpriteByTwo: ; 2fe40 (b:7e40)
- ld de, S_SPRITEBUFFER1 + (4*4*8) - 5 ; last byte of input data, last 4 rows already skipped
- ld hl, S_SPRITEBUFFER0 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
- call ScaleLastSpriteColumnByTwo ; last tile column is special case
- call ScaleFirstThreeSpriteColumnsByTwo ; scale first 3 tile columns
- ld de, S_SPRITEBUFFER2 + (4*4*8) - 5 ; last byte of input data, last 4 rows already skipped
- ld hl, S_SPRITEBUFFER1 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
- call ScaleLastSpriteColumnByTwo ; last tile column is special case
-
-ScaleFirstThreeSpriteColumnsByTwo: ; 2fe55 (b:7e55)
- ld b, $3 ; 3 tile columns
-.columnLoop
- ld c, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
-.columnInnerLoop
- push bc
- ld a, [de]
- ld bc, -(7*8)+1 ; $ffc9, scale lower nybble and seek to previous output column
- call ScalePixelsByTwo
- ld a, [de]
- dec de
- swap a
- ld bc, 7*8+1-2 ; $37, scale upper nybble and seek back to current output column and to the next 2 rows
- call ScalePixelsByTwo
- pop bc
- dec c
- jr nz, .columnInnerLoop
- dec de
- dec de
- dec de
- dec de
- ld a, b
- ld bc, -7*8 ; $ffc8, skip one output column (which has already been written along with the current one)
- add hl, bc
- ld b, a
- dec b
- jr nz, .columnLoop
- ret
-
-ScaleLastSpriteColumnByTwo: ; 2fe7d (b:7e7d)
- ld a, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
- ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
- ld bc, -1 ; $ffff
-.columnInnerLoop
- ld a, [de]
- dec de
- swap a ; only high nybble contains information
- call ScalePixelsByTwo
- ld a, [H_SPRITEINTERLACECOUNTER] ; $ff8b
- dec a
- ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
- jr nz, .columnInnerLoop
- dec de ; skip last 4 rows of new column
- dec de
- dec de
- dec de
- ret
-
-; scales the given 4 bits in a (4x1 pixels) to 2 output bytes (8x2 pixels)
-; hl: destination pointer
-; bc: destination pointer offset (added after the two bytes have been written)
-ScalePixelsByTwo: ; 2fe97 (b:7e97)
- push hl
- and $f
- ld hl, DuplicateBitsTable
- add l
- ld l, a
- jr nc, .noCarry
- inc h
-.noCarry
- ld a, [hl]
- pop hl
- ld [hld], a ; write output byte twice to make it 2 pixels high
- ld [hl], a
- add hl, bc ; add offset
- ret
-
-; repeats each input bit twice
-DuplicateBitsTable: ; 2fea8 (b:7ea8)
- db $00, $03, $0c, $0f
- db $30, $33, $3c, $3f
- db $c0, $c3, $cc, $cf
- db $f0, $f3, $fc, $ff
-
-PayDayEffect_ ; 2feb8 (b:7eb8)
- xor a
- ld hl, wcd6d
- ld [hli], a
- ld a, [H_WHOSETURN]
- and a
- ld a, [wBattleMonLevel]
- jr z, .asm_2fec8
- ld a, [wEnemyMonLevel]
-.asm_2fec8
- add a
- ld [H_DIVIDEND + 3], a
- xor a
- ld [H_DIVIDEND], a
- ld [H_DIVIDEND + 1], a
- ld [H_DIVIDEND + 2], a
- ld a, $64
- ld [H_DIVISOR], a
- ld b, $4
- call Divide
- ld a, [H_QUOTIENT + 3]
- ld [hli], a
- ld a, [H_REMAINDER]
- ld [H_DIVIDEND + 3], a
- ld a, $a
- ld [H_DIVISOR], a
- ld b, $4
- call Divide
- ld a, [H_QUOTIENT + 3]
- swap a
- ld b, a
- ld a, [H_REMAINDER]
- add b
- ld [hl], a
- ld de, wTotalPayDayMoney + 2
- ld c, $3
- predef AddBCDPredef
- ld hl, CoinsScatteredText
- jp PrintText
-
-CoinsScatteredText: ; 2ff04 (b:7f04)
- TX_FAR _CoinsScatteredText
- db "@"
--- /dev/null
+++ b/engine/battle/bank_e_misc.asm
@@ -1,0 +1,122 @@
+; formats a string at wMovesString that lists the moves at wMoves
+FormatMovesString: ; 39b87 (e:5b87)
+ ld hl, wMoves
+ ld de, wMovesString
+ ld b, $0
+.printMoveNameLoop
+ ld a, [hli]
+ and a ; end of move list?
+ jr z, .printDashLoop ; print dashes when no moves are left
+ push hl
+ ld [wd0b5], a
+ ld a, BANK(MoveNames)
+ ld [wPredefBank], a
+ ld a, MOVE_NAME
+ ld [wNameListType], a
+ call GetName
+ ld hl, wcd6d
+.copyNameLoop
+ ld a, [hli]
+ cp $50
+ jr z, .doneCopyingName
+ ld [de], a
+ inc de
+ jr .copyNameLoop
+.doneCopyingName
+ ld a, b
+ ld [wcd6c], a
+ inc b
+ ld a, $4e ; line break
+ ld [de], a
+ inc de
+ pop hl
+ ld a, b
+ cp NUM_MOVES
+ jr z, .done
+ jr .printMoveNameLoop
+.printDashLoop
+ ld a, "-"
+ ld [de], a
+ inc de
+ inc b
+ ld a, b
+ cp NUM_MOVES
+ jr z, .done
+ ld a, $4e ; line break
+ ld [de], a
+ inc de
+ jr .printDashLoop
+.done
+ ld a, "@"
+ ld [de], a
+ ret
+
+; XXX this is called in a few places, but it doesn't appear to do anything useful
+Func_39bd5: ; 39bd5 (e:5bd5)
+ ld a, [wd11b]
+ cp $1
+ jr nz, .asm_39be6
+ ld hl, wEnemyPartyCount
+ ld de, wEnemyMonOT
+ ld a, ENEMYOT_NAME
+ jr .asm_39c18
+.asm_39be6
+ cp $4
+ jr nz, .calcAttackStat4
+ ld hl, wPartyCount
+ ld de, wPartyMonOT
+ ld a, PLAYEROT_NAME
+ jr .asm_39c18
+.calcAttackStat4
+ cp $5
+ jr nz, .asm_39c02
+ ld hl, wStringBuffer2 + 11
+ ld de, MonsterNames
+ ld a, MONSTER_NAME
+ jr .asm_39c18
+.asm_39c02
+ cp $2
+ jr nz, .asm_39c10
+ ld hl, wNumBagItems
+ ld de, ItemNames
+ ld a, ITEM_NAME
+ jr .asm_39c18
+.asm_39c10
+ ld hl, wStringBuffer2 + 11
+ ld de, ItemNames
+ ld a, ITEM_NAME
+.asm_39c18
+ ld [wNameListType], a
+ ld a, l
+ ld [wList], a
+ ld a, h
+ ld [wList + 1], a
+ ld a, e
+ ld [wcf8d], a
+ ld a, d
+ ld [wcf8e], a
+ ld bc, ItemPrices
+ ld a, c
+ ld [wItemPrices], a
+ ld a, b
+ ld [wItemPrices + 1], a
+ ret
+
+; get species of mon e in list [wcc49] for LoadMonData
+GetMonSpecies: ; 39c37 (e:5c37)
+ ld hl, wPartySpecies
+ ld a, [wcc49]
+ and a
+ jr z, .getSpecies
+ dec a
+ jr z, .enemyParty
+ ld hl, wBoxSpecies
+ jr .getSpecies
+.enemyParty
+ ld hl, wEnemyPartyMons
+.getSpecies
+ ld d, 0
+ add hl, de
+ ld a, [hl]
+ ld [wcf91], a
+ ret
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/battle_transitions.asm
@@ -1,0 +1,815 @@
+BattleTransition: ; 7096d (1c:496d)
+ ld a, $1
+ ld [H_AUTOBGTRANSFERENABLED], a
+ call Delay3
+ xor a
+ ld [hWY], a
+ dec a
+ ld [wUpdateSpritesEnabled], a
+ call DelayFrame
+ ld hl, wSpriteStateData1 + 2
+ ld a, [H_DOWNARROWBLINKCNT2]
+ ld c, a
+ ld b, $0
+ ld de, $10
+.loop1
+ ld a, [hl]
+ cp $ff
+ jr z, .skip1
+ inc b
+.skip1
+ add hl, de
+ dec c
+ jr nz, .loop1
+ ld hl, wOAMBuffer + $10
+ ld c, $9
+.loop2
+ ld a, b
+ swap a
+ cp l
+ jr z, .skip2
+ push hl
+ push bc
+ ld bc, $10
+ xor a
+ call FillMemory
+ pop bc
+ pop hl
+.skip2
+ ld de, $10
+ add hl, de
+ dec c
+ jr nz, .loop2
+ call Delay3
+ call LoadBattleTransitionTile
+ ld bc, $0
+ ld a, [wLinkState]
+ cp LINK_STATE_BATTLING
+ jr z, .linkBattle
+ call GetBattleTransitionID_WildOrTrainer
+ call GetBattleTransitionID_CompareLevels
+ call GetBattleTransitionID_IsDungeonMap
+.linkBattle
+ ld hl, BattleTransitions
+ add hl, bc
+ add hl, bc
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp [hl]
+
+; the three GetBattleTransitionID functions set the first
+; three bits of c, which determines what transition animation
+; to play at the beginning of a battle
+; bit 0: set if trainer battle
+; bit 1: set if enemy is at least 3 levels higher than player
+; bit 2: set if dungeon map
+BattleTransitions: ; 709d2 (1c:49d2)
+ dw BattleTransition_DoubleCircle ; %000
+ dw BattleTransition_Spiral ; %001
+ dw BattleTransition_Circle ; %010
+ dw BattleTransition_Spiral ; %011
+ dw BattleTransition_HorizontalStripes ; %100
+ dw BattleTransition_Shrink ; %101
+ dw BattleTransition_VerticalStripes ; %110
+ dw BattleTransition_Split ; %111
+
+GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2)
+ ld a, [W_CUROPPONENT]
+ cp $c8
+ jr nc, .trainer
+ res 0, c
+ ret
+.trainer
+ set 0, c
+ ret
+
+GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef)
+ ld hl, wPartyMon1HP
+.faintedLoop
+ ld a, [hli]
+ or [hl]
+ jr nz, .notFainted
+ ld de, wPartyMon2 - (wPartyMon1 + 1)
+ add hl, de
+ jr .faintedLoop
+.notFainted
+ ld de, wPartyMon1Level - (wPartyMon1HP + 1)
+ add hl, de
+ ld a, [hl]
+ add $3
+ ld e, a
+ ld a, [W_CURENEMYLVL]
+ sub e
+ jr nc, .highLevelEnemy
+ res 1, c
+ ld a, $1
+ ld [wcd47], a
+ ret
+.highLevelEnemy
+ set 1, c
+ xor a
+ ld [wcd47], a
+ ret
+
+; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps,
+; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE
+; and SILPH_CO_[9-11]F as dungeon maps
+GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19)
+ ld a, [W_CURMAP]
+ ld e, a
+ ld hl, DungeonMaps1
+.loop1
+ ld a, [hli]
+ cp $ff
+ jr z, .noMatch1
+ cp e
+ jr nz, .loop1
+.match
+ set 2, c
+ ret
+.noMatch1
+ ld hl, DungeonMaps2
+.loop2
+ ld a, [hli]
+ cp $ff
+ jr z, .noMatch2
+ ld d, a
+ ld a, [hli]
+ cp e
+ jr c, .loop2
+ ld a, e
+ cp d
+ jr nc, .match
+.noMatch2
+ res 2, c
+ ret
+
+; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
+; is equal to one of these maps
+DungeonMaps1: ; 70a3f (1c:4a3f)
+ db VIRIDIAN_FOREST
+ db ROCK_TUNNEL_1
+ db SEAFOAM_ISLANDS_1
+ db ROCK_TUNNEL_2
+ db $FF
+
+; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
+; is in between or equal to each pair of maps
+DungeonMaps2: ; 70a44 (1c:4a44)
+ ; all MT_MOON maps
+ db MT_MOON_1
+ db MT_MOON_3
+
+ ; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME
+ db SS_ANNE_1
+ db HALL_OF_FAME
+
+ ; all POKEMONTOWER maps and Lavender Town buildings
+ db LAVENDER_POKECENTER
+ db LAVENDER_HOUSE_2
+
+ ; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps,
+ ; except for SILPH_CO_1F
+ db SILPH_CO_2F
+ db UNKNOWN_DUNGEON_1
+ db $FF
+
+LoadBattleTransitionTile: ; 70a4d (1c:4a4d)
+ ld hl, vChars1 + $7f0
+ ld de, BattleTransitionTile
+ ld bc, (BANK(BattleTransitionTile) << 8) + $01
+ jp CopyVideoData
+
+BattleTransitionTile: ; 70a59 (1c:4a59)
+ INCBIN "gfx/battle_transition.2bpp"
+
+BattleTransition_BlackScreen: ; 70a69 (1c:4a69)
+ ld a, $ff
+ ld [rBGP], a
+ ld [rOBP0], a
+ ld [rOBP1], a
+ ret
+
+; for non-dungeon trainer battles
+; called regardless of mon levels, but does an
+; outward spiral if enemy is at least 3 levels
+; higher than player and does an inward spiral otherwise
+BattleTransition_Spiral: ; 70a72 (1c:4a72)
+ ld a, [wcd47]
+ and a
+ jr z, .outwardSpiral
+ call BattleTransition_InwardSpiral
+ jr .done
+.outwardSpiral
+ hlCoord 10, 10
+ ld a, $3
+ ld [wd09f], a
+ ld a, l
+ ld [wd09b], a
+ ld a, h
+ ld [wd09a], a
+ ld b, $78
+.loop1
+ ld c, $3
+.loop2
+ push bc
+ call BattleTransition_OutwardSpiral_
+ pop bc
+ dec c
+ jr nz, .loop2
+ call DelayFrame
+ dec b
+ jr nz, .loop1
+.done
+ call BattleTransition_BlackScreen
+ xor a
+ ld [wd09b], a
+ ld [wd09a], a
+ ret
+
+BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa)
+ ld a, $7
+ ld [wWhichTrade], a
+ ld hl, wTileMap
+ ld c, $11
+ ld de, $14
+ call BattleTransition_InwardSpiral_
+ inc c
+ jr .skip
+.loop
+ ld de, $14
+ call BattleTransition_InwardSpiral_
+.skip
+ inc c
+ ld de, $1
+ call BattleTransition_InwardSpiral_
+ dec c
+ dec c
+ ld de, $ffec
+ call BattleTransition_InwardSpiral_
+ inc c
+ ld de, rIE
+ call BattleTransition_InwardSpiral_
+ dec c
+ dec c
+ ld a, c
+ and a
+ jr nz, .loop
+ ret
+
+BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0)
+ push bc
+.loop
+ ld [hl], $ff
+ add hl, de
+ push bc
+ ld a, [wWhichTrade]
+ dec a
+ jr nz, .skip
+ call BattleTransition_TransferDelay3
+ ld a, $7
+.skip
+ ld [wWhichTrade], a
+ pop bc
+ dec c
+ jr nz, .loop
+ pop bc
+ ret
+
+BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9)
+ ld bc, $ffec
+ ld de, $14
+ ld a, [wd09b]
+ ld l, a
+ ld a, [wd09a]
+ ld h, a
+ ld a, [wd09f]
+ cp $0
+ jr z, .zero
+ cp $1
+ jr z, .one
+ cp $2
+ jr z, .two
+ cp $3
+ jr z, .three
+.done1
+ ld [hl], $ff
+.done2_
+ ld a, l
+ ld [wd09b], a
+ ld a, h
+ ld [wd09a], a
+ ret
+.zero
+ dec hl
+ ld a, [hl]
+ cp $ff
+ jr nz, .done2
+ inc hl
+ add hl, bc
+ jr .done1
+.one
+ add hl, de
+ ld a, [hl]
+ cp $ff
+ jr nz, .done2
+ add hl, bc
+ dec hl
+ jr .done1
+.two
+ inc hl
+ ld a, [hl]
+ cp $ff
+ jr nz, .done2
+ dec hl
+ add hl, de
+ jr .done1
+.three
+ add hl, bc
+ ld a, [hl]
+ cp $ff
+ jr nz, .done2
+ add hl, de
+ inc hl
+ jr .done1
+.done2
+ ld [hl], $ff
+ ld a, [wd09f]
+ inc a
+ cp $4
+ jr nz, .skip
+ xor a
+.skip
+ ld [wd09f], a
+ jr .done2_
+
+FlashScreen:
+BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d)
+ ld hl, BattleTransition_FlashScreenPalettes
+.loop
+ ld a, [hli]
+ cp $1
+ jr z, .done
+ ld [rBGP], a
+ ld c, $2
+ call DelayFrames
+ jr .loop
+.done
+ dec b
+ jr nz, BattleTransition_FlashScreen_
+ ret
+
+BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72)
+ db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4
+ db $01 ; terminator
+
+; used for low level trainer dungeon battles
+BattleTransition_Shrink: ; 70b7f (1c:4b7f)
+ ld c, $9
+.loop
+ push bc
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ hlCoord 0, 7
+ deCoord 0, 8
+ ld bc, $ffd8
+ call BattleTransition_CopyTiles1
+ hlCoord 0, 10
+ deCoord 0, 9
+ ld bc, $28
+ call BattleTransition_CopyTiles1
+ hlCoord 8, 0
+ deCoord 9, 0
+ ld bc, $fffe
+ call BattleTransition_CopyTiles2
+ hlCoord 11, 0
+ deCoord 10, 0
+ ld bc, $2
+ call BattleTransition_CopyTiles2
+ ld a, $1
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ld c, $6
+ call DelayFrames
+ pop bc
+ dec c
+ jr nz, .loop
+ call BattleTransition_BlackScreen
+ ld c, $a
+ jp DelayFrames
+
+; used for high level trainer dungeon battles
+BattleTransition_Split: ; 70bca (1c:4bca)
+ ld c, $9
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+ push bc
+ hlCoord 0, 16
+ deCoord 0, 17
+ ld bc, $ffd8
+ call BattleTransition_CopyTiles1
+ hlCoord 0, 1
+ ld de, wTileMap
+ ld bc, $28
+ call BattleTransition_CopyTiles1
+ hlCoord 18, 0
+ deCoord 19, 0
+ ld bc, $fffe
+ call BattleTransition_CopyTiles2
+ hlCoord 1, 0
+ ld de, wTileMap
+ ld bc, $2
+ call BattleTransition_CopyTiles2
+ call BattleTransition_TransferDelay3
+ call Delay3
+ pop bc
+ dec c
+ jr nz, .loop
+ call BattleTransition_BlackScreen
+ ld c, $a
+ jp DelayFrames
+
+BattleTransition_CopyTiles1: ; 70c12 (1c:4c12)
+ ld a, c
+ ld [wWhichTrade], a
+ ld a, b
+ ld [wTrainerEngageDistance], a
+ ld c, $8
+.loop1
+ push bc
+ push hl
+ push de
+ ld bc, $14
+ call CopyData
+ pop hl
+ pop de
+ ld a, [wWhichTrade]
+ ld c, a
+ ld a, [wTrainerEngageDistance]
+ ld b, a
+ add hl, bc
+ pop bc
+ dec c
+ jr nz, .loop1
+ ld l, e
+ ld h, d
+ ld a, $ff
+ ld c, $14
+.loop2
+ ld [hli], a
+ dec c
+ jr nz, .loop2
+ ret
+
+BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f)
+ ld a, c
+ ld [wWhichTrade], a
+ ld a, b
+ ld [wTrainerEngageDistance], a
+ ld c, $9
+.loop1
+ push bc
+ push hl
+ push de
+ ld c, $12
+.loop2
+ ld a, [hl]
+ ld [de], a
+ ld a, e
+ add $14
+ jr nc, .noCarry1
+ inc d
+.noCarry1
+ ld e, a
+ ld a, l
+ add $14
+ jr nc, .noCarry2
+ inc h
+.noCarry2
+ ld l, a
+ dec c
+ jr nz, .loop2
+ pop hl
+ pop de
+ ld a, [wWhichTrade]
+ ld c, a
+ ld a, [wTrainerEngageDistance]
+ ld b, a
+ add hl, bc
+ pop bc
+ dec c
+ jr nz, .loop1
+ ld l, e
+ ld h, d
+ ld de, $14
+ ld c, $12
+.loop3
+ ld [hl], $ff
+ add hl, de
+ dec c
+ jr nz, .loop3
+ ret
+
+; used for high level wild dungeon battles
+BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e)
+ ld c, $12
+ ld hl, wTileMap
+ deCoord 1, 17
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+ push bc
+ push hl
+ push de
+ push de
+ call BattleTransition_VerticalStripes_
+ pop hl
+ call BattleTransition_VerticalStripes_
+ call BattleTransition_TransferDelay3
+ pop hl
+ ld bc, $ffec
+ add hl, bc
+ ld e, l
+ ld d, h
+ pop hl
+ ld bc, $14
+ add hl, bc
+ pop bc
+ dec c
+ jr nz, .loop
+ jp BattleTransition_BlackScreen
+
+BattleTransition_VerticalStripes_: ; 70caa (1c:4caa)
+ ld c, $a
+.loop
+ ld [hl], $ff
+ inc hl
+ inc hl
+ dec c
+ jr nz, .loop
+ ret
+
+; used for low level wild dungeon battles
+BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4)
+ ld c, $14
+ ld hl, wTileMap
+ deCoord 19, 1
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+ push bc
+ push hl
+ push de
+ push de
+ call BattleTransition_HorizontalStripes_
+ pop hl
+ call BattleTransition_HorizontalStripes_
+ call BattleTransition_TransferDelay3
+ pop de
+ pop hl
+ pop bc
+ inc hl
+ dec de
+ dec c
+ jr nz, .loop
+ jp BattleTransition_BlackScreen
+
+BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8)
+ ld c, $9
+ ld de, $28
+.loop
+ ld [hl], $ff
+ add hl, de
+ dec c
+ jr nz, .loop
+ ret
+
+; used for high level wild non-dungeon battles
+; makes one full circle around the screen
+; by animating each half circle one at a time
+BattleTransition_Circle: ; 70ce4 (1c:4ce4)
+ call BattleTransition_FlashScreen
+ ld bc, $000a
+ ld hl, BattleTransition_HalfCircle1
+ call BattleTransition_Circle_Sub1
+ ld c, $a
+ ld b, $1
+ ld hl, BattleTransition_HalfCircle2
+ call BattleTransition_Circle_Sub1
+ jp BattleTransition_BlackScreen
+
+BattleTransition_FlashScreen: ; 70cfd (1c:4cfd)
+ ld b, $3
+ call BattleTransition_FlashScreen_
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ret
+
+BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06)
+ push bc
+ push hl
+ ld a, b
+ call BattleTransition_Circle_Sub2
+ pop hl
+ ld bc, $0005
+ add hl, bc
+ call BattleTransition_TransferDelay3
+ pop bc
+ dec c
+ jr nz, BattleTransition_Circle_Sub1
+ ret
+
+BattleTransition_TransferDelay3: ; 70d19 (1c:4d19)
+ ld a, $1
+ ld [H_AUTOBGTRANSFERENABLED], a
+ call Delay3
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a
+ ret
+
+; used for low level wild non-dungeon battles
+; makes two half circles around the screen
+; by animating both half circles at the same time
+BattleTransition_DoubleCircle: ; 70d24 (1c:4d24)
+ call BattleTransition_FlashScreen
+ ld c, $a
+ ld hl, BattleTransition_HalfCircle1
+ ld de, BattleTransition_HalfCircle2
+.loop
+ push bc
+ push hl
+ push de
+ push de
+ xor a
+ call BattleTransition_Circle_Sub2
+ pop hl
+ ld a, $1
+ call BattleTransition_Circle_Sub2
+ pop hl
+ ld bc, $5
+ add hl, bc
+ ld e, l
+ ld d, h
+ pop hl
+ add hl, bc
+ call BattleTransition_TransferDelay3
+ pop bc
+ dec c
+ jr nz, .loop
+ jp BattleTransition_BlackScreen
+
+BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50)
+ ld [wWhichTrade], a
+ ld a, [hli]
+ ld [wTrainerEngageDistance], a
+ ld a, [hli]
+ ld e, a
+ ld a, [hli]
+ ld d, a
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp BattleTransition_Circle_Sub3
+
+BattleTransition_HalfCircle1: ; 70d61 (1c:4d61)
+ db $01
+ dw BattleTransition_CircleData1
+ dwCoord 18, 6
+
+ db $01
+ dw BattleTransition_CircleData2
+ dwCoord 19, 3
+
+ db $01
+ dw BattleTransition_CircleData3
+ dwCoord 18, 0
+
+ db $01
+ dw BattleTransition_CircleData4
+ dwCoord 14, 0
+
+ db $01
+ dw BattleTransition_CircleData5
+ dwCoord 10, 0
+
+ db $00
+ dw BattleTransition_CircleData5
+ dwCoord 9, 0
+
+ db $00
+ dw BattleTransition_CircleData4
+ dwCoord 5, 0
+
+ db $00
+ dw BattleTransition_CircleData3
+ dwCoord 1, 0
+
+ db $00
+ dw BattleTransition_CircleData2
+ dwCoord 0, 3
+
+ db $00
+ dw BattleTransition_CircleData1
+ dwCoord 1, 6
+
+BattleTransition_HalfCircle2: ; 70d93 (1c:4d93)
+ db $00
+ dw BattleTransition_CircleData1
+ dwCoord 1, 11
+
+ db $00
+ dw BattleTransition_CircleData2
+ dwCoord 0, 14
+
+ db $00
+ dw BattleTransition_CircleData3
+ dwCoord 1, 17
+
+ db $00
+ dw BattleTransition_CircleData4
+ dwCoord 5, 17
+
+ db $00
+ dw BattleTransition_CircleData5
+ dwCoord 9, 17
+
+ db $01
+ dw BattleTransition_CircleData5
+ dwCoord 10, 17
+
+ db $01
+ dw BattleTransition_CircleData4
+ dwCoord 14, 17
+
+ db $01
+ dw BattleTransition_CircleData3
+ dwCoord 18, 17
+
+ db $01
+ dw BattleTransition_CircleData2
+ dwCoord 19, 14
+
+ db $01
+ dw BattleTransition_CircleData1
+ dwCoord 18, 11
+
+BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5)
+ push hl
+ ld a, [de]
+ ld c, a
+ inc de
+.loop1
+ ld [hl], $ff
+ ld a, [wTrainerEngageDistance]
+ and a
+ jr z, .skip1
+ inc hl
+ jr .skip2
+.skip1
+ dec hl
+.skip2
+ dec c
+ jr nz, .loop1
+ pop hl
+ ld a, [wWhichTrade]
+ and a
+ ld bc, $14
+ jr z, .skip3
+ ld bc, $ffec
+.skip3
+ add hl, bc
+ ld a, [de]
+ inc de
+ cp $ff
+ ret z
+ and a
+ jr z, BattleTransition_Circle_Sub3
+ ld c, a
+.loop2
+ ld a, [wTrainerEngageDistance]
+ and a
+ jr z, .skip4
+ dec hl
+ jr .skip5
+.skip4
+ inc hl
+.skip5
+ dec c
+ jr nz, .loop2
+ jr BattleTransition_Circle_Sub3
+
+BattleTransition_CircleData1: ; 70dfe (1c:4dfe)
+ db $02,$03,$05,$04,$09,$FF
+
+BattleTransition_CircleData2: ; 70e04 (1c:4e04)
+ db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF
+
+BattleTransition_CircleData3: ; 70e0e (1c:4e0e)
+ db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF
+
+BattleTransition_CircleData4: ; 70e20 (1c:4e20)
+ db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF
+
+BattleTransition_CircleData5: ; 70e2e (1c:4e2e)
+ db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF
--- a/engine/battle/c.asm
+++ /dev/null
@@ -1,58 +1,0 @@
-MistEffect_: ; 33f2b (c:7f2b)
- ld hl, W_PLAYERBATTSTATUS2
- ld a, [$fff3]
- and a
- jr z, .asm_33f36
- ld hl, W_ENEMYBATTSTATUS2
-.asm_33f36
- bit ProtectedByMist, [hl] ; is mon protected by mist?
- jr nz, .asm_33f4a
- set ProtectedByMist, [hl] ; mon is now protected by mist
- callab PlayCurrentMoveAnimation
- ld hl, ShroudedInMistText
- jp PrintText
-.asm_33f4a
- ld hl, PrintButItFailedText_
- ld b, BANK(PrintButItFailedText_)
- jp Bankswitch
-
-ShroudedInMistText: ; 33f52 (c:7f52)
- TX_FAR _ShroudedInMistText
- db "@"
-
-OneHitKOEffect_: ; 33f57 (c:7f57)
- ld hl, W_DAMAGE
- xor a
- ld [hli], a
- ld [hl], a ; set the damage output to zero
- dec a
- ld [wCriticalHitOrOHKO], a
- ld hl, wBattleMonSpeed + 1
- ld de, wEnemyMonSpeed + 1
- ld a, [H_WHOSETURN] ; $fff3
- and a
- jr z, .asm_33f72
- ld hl, wEnemyMonSpeed + 1
- ld de, wBattleMonSpeed + 1
-.asm_33f72
- ld a, [de]
- dec de
- ld b, a
- ld a, [hld]
- sub b
- ld a, [de]
- ld b, a
- ld a, [hl]
- sbc b
- jr c, .asm_33f8a
- ld hl, W_DAMAGE
- ld a, $ff
- ld [hli], a
- ld [hl], a
- ld a, $2
- ld [wCriticalHitOrOHKO], a
- ret
-.asm_33f8a
- ld a, $1
- ld [W_MOVEMISSED], a
- ret
--- /dev/null
+++ b/engine/battle/common_text.asm
@@ -1,0 +1,238 @@
+PrintBeginningBattleText: ; 58d99 (16:4d99)
+ ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+ dec a
+ jr nz, .trainerBattle
+ ld a, [W_CURMAP] ; W_CURMAP
+ cp POKEMONTOWER_3
+ jr c, .notPokemonTower
+ cp LAVENDER_HOUSE_1
+ jr c, .pokemonTower
+.notPokemonTower
+ ld a, [wEnemyMonSpecies2]
+ call PlayCry
+ ld hl, WildMonAppearedText
+ ld a, [W_MOVEMISSED] ; W_MOVEMISSED
+ and a
+ jr z, .notFishing
+ ld hl, HookedMonAttackedText
+.notFishing
+ jr .wildBattle
+.trainerBattle
+ call .playSFX
+ ld c, $14
+ call DelayFrames
+ ld hl, TrainerWantsToFightText
+.wildBattle
+ push hl
+ callab DrawAllPokeballs
+ pop hl
+ call PrintText
+ jr .done
+.pokemonTower
+ ld b, SILPH_SCOPE
+ call IsItemInBag
+ ld a, [wEnemyMonSpecies2]
+ ld [wcf91], a
+ cp MAROWAK
+ jr z, .isMarowak
+ ld a, b
+ and a
+ jr z, .noSilphScope
+ callab LoadEnemyMonData
+ jr .notPokemonTower
+.noSilphScope
+ ld hl, EnemyAppearedText
+ call PrintText
+ ld hl, GhostCantBeIDdText
+ call PrintText
+ jr .done
+.isMarowak
+ ld a, b
+ and a
+ jr z, .noSilphScope
+ ld hl, EnemyAppearedText
+ call PrintText
+ ld hl, UnveiledGhostText
+ call PrintText
+ callab LoadEnemyMonData
+ callab MarowakAnim
+ ld hl, WildMonAppearedText
+ call PrintText
+
+.playSFX
+ xor a
+ ld [wc0f1], a
+ ld a, $80
+ ld [wc0f2], a
+ ld a, (SFX_08_77 - SFX_Headers_08) / 3
+ call PlaySound
+ jp WaitForSoundToFinish
+.done
+ ret
+
+WildMonAppearedText: ; 58e3b (16:4e3b)
+ TX_FAR _WildMonAppearedText
+ db "@"
+
+HookedMonAttackedText: ; 58e40 (16:4e40)
+ TX_FAR _HookedMonAttackedText
+ db "@"
+
+EnemyAppearedText: ; 58e45 (16:4e45)
+ TX_FAR _EnemyAppearedText
+ db "@"
+
+TrainerWantsToFightText: ; 58e4a (16:4e4a)
+ TX_FAR _TrainerWantsToFightText
+ db "@"
+
+UnveiledGhostText: ; 58e4f (16:4e4f)
+ TX_FAR _UnveiledGhostText
+ db "@"
+
+GhostCantBeIDdText: ; 58e54 (16:4e54)
+ TX_FAR _GhostCantBeIDdText
+ db "@"
+
+PrintSendOutMonMessage: ; 58e59 (16:4e59)
+ ld hl, wEnemyMonHP
+ ld a, [hli]
+ or [hl]
+ ld hl, GoText
+ jr z, .printText
+ xor a
+ ld [H_MULTIPLICAND], a
+ ld hl, wEnemyMonHP
+ ld a, [hli]
+ ld [wcce3], a
+ ld [H_MULTIPLICAND + 1], a
+ ld a, [hl]
+ ld [wcce4], a
+ ld [H_MULTIPLICAND + 2], a
+ ld a, 25
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld hl, wEnemyMonMaxHP
+ ld a, [hli]
+ ld b, [hl]
+ srl a
+ rr b
+ srl a
+ rr b
+ ld a, b
+ ld b, $4
+ ld [H_DIVISOR], a ; enemy mon max HP divided by 4
+ call Divide
+ ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP
+ ld hl, GoText ; 70% or greater
+ cp 70
+ jr nc, .printText
+ ld hl, DoItText ; 40% - 69%
+ cp 40
+ jr nc, .printText
+ ld hl, GetmText ; 10% - 39%
+ cp 10
+ jr nc, .printText
+ ld hl, EnemysWeakText ; 0% - 9%
+.printText
+ jp PrintText
+
+GoText: ; 58eae (16:4eae)
+ TX_FAR _GoText
+ db $08 ; asm
+ jr PrintPlayerMon1Text
+
+DoItText: ; 58eb5 (16:4eb5)
+ TX_FAR _DoItText
+ db $08 ; asm
+ jr PrintPlayerMon1Text
+
+GetmText: ; 58ebc (16:4ebc)
+ TX_FAR _GetmText
+ db $08 ; asm
+ jr PrintPlayerMon1Text
+
+EnemysWeakText: ; 58ec3 (16:4ec3)
+ TX_FAR _EnemysWeakText
+ db $08 ; asm
+
+PrintPlayerMon1Text:
+ ld hl, PlayerMon1Text
+ ret
+
+PlayerMon1Text: ; 58ecc (16:4ecc)
+ TX_FAR _PlayerMon1Text
+ db "@"
+
+RetreatMon: ; 58ed1 (16:4ed1)
+ ld hl, PlayerMon2Text
+ jp PrintText
+
+PlayerMon2Text: ; 58ed7 (16:4ed7)
+ TX_FAR _PlayerMon2Text
+ db $08 ; asm
+ push de
+ push bc
+ ld hl, wEnemyMonHP + 1
+ ld de, wcce4
+ ld b, [hl]
+ dec hl
+ ld a, [de]
+ sub b
+ ld [$ff98], a
+ dec de
+ ld b, [hl]
+ ld a, [de]
+ sbc b
+ ld [$ff97], a
+ ld a, $19
+ ld [H_POWEROFTEN], a
+ call Multiply
+ ld hl, wEnemyMonMaxHP
+ ld a, [hli]
+ ld b, [hl]
+ srl a
+ rr b
+ srl a
+ rr b
+ ld a, b
+ ld b, $4
+ ld [H_POWEROFTEN], a
+ call Divide
+ pop bc
+ pop de
+ ld a, [$ff98]
+ ld hl, EnoughText
+ and a
+ ret z
+ ld hl, ComeBackText
+ cp $1e
+ ret c
+ ld hl, OKExclamationText
+ cp $46
+ ret c
+ ld hl, GoodText
+ ret
+
+EnoughText: ; 58f25 (16:4f25)
+ TX_FAR _EnoughText
+ db $08 ; asm
+ jr PrintComeBackText
+
+OKExclamationText: ; 58f2c (16:4f2c)
+ TX_FAR _OKExclamationText
+ db $08 ; asm
+ jr PrintComeBackText
+
+GoodText: ; 58f33 (16:4f33)
+ TX_FAR _GoodText
+ db $08 ; asm
+ jr PrintComeBackText
+
+PrintComeBackText: ; 58f3a (16:4f3a)
+ ld hl, ComeBackText
+ ret
+
+ComeBackText: ; 58f3e (16:4f3e)
+ TX_FAR _ComeBackText
+ db "@"
--- a/engine/battle/core.asm
+++ b/engine/battle/core.asm
@@ -454,7 +454,8 @@
ld b, 0
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
+ cp METRONOME ; a MIRROR MOVE check is missing, might lead to a desync in link battles
+ ; when combined with multi-turn moves
jr nz, .asm_3c2dd
ld [wPlayerSelectedMove], a
.asm_3c2dd
@@ -581,7 +582,7 @@
.poisoned
call PrintText
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a,BURN_PSN_ANIM
call PlayMoveAnimation ; play burn/poison animation
pop hl
@@ -602,7 +603,7 @@
xor $1
ld [H_WHOSETURN], a
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a,ABSORB
call PlayMoveAnimation ; play leech seed animation (from opposing mon)
pop af
@@ -874,7 +875,7 @@
call WaitForSoundToFinish
jr .sfxplayed
.wild_win
- call Func_3c643
+ call EndLowHealthAlarm
ld a, MUSIC_DEFEATED_WILD_MON
call PlayBattleVictoryMusic
.sfxplayed
@@ -918,7 +919,7 @@
; 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
xor a
- ld [wcc5b], a
+ ld [wBoostExpByExpAll], a
callab GainExperience
pop af
ret z ; return if no exp all
@@ -927,7 +928,7 @@
; 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
ld a, $1
- ld [wcc5b], a
+ ld [wBoostExpByExpAll], a
ld a, [wPartyCount]
ld b, 0
.gainExpFlagsLoop
@@ -945,7 +946,7 @@
TX_FAR _EnemyMonFaintedText
db "@"
-Func_3c643: ; 3c643 (f:4643)
+EndLowHealthAlarm: ; 3c643 (f:4643)
xor a
ld [wLowHealthAlarm], a ;disable low health alarm
ld [wc02a], a
@@ -990,12 +991,12 @@
xor a
ld [W_ENEMYMOVENUM], a
ld [wcd6a], a
- ld [wccd5], a
+ ld [wAILayer2Encouragement], a
inc a ; reset Z flag
ret
TrainerBattleVictory: ; 3c696 (f:4696)
- call Func_3c643
+ call EndLowHealthAlarm
ld b, MUSIC_DEFEATED_GYM_LEADER
ld a, [W_GYMLEADERNO]
and a
@@ -1640,7 +1641,8 @@
ld b, a
ld a, [H_QUOTIENT + 3]
cp b
- 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
+ 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
; can't escape
ld a, $1
ld [wcd6a], a
@@ -1809,8 +1811,8 @@
ld hl, wcc2d
ld [hli], a
ld [hl], a
- ld [wcc5b], a
- ld [wd05b], a
+ ld [wBoostExpByExpAll], a
+ ld [wDamageMultipliers], a
ld [W_PLAYERMOVENUM], a
ld hl, wPlayerUsedMove
ld [hli], a
@@ -2046,8 +2048,10 @@
jp GoPAL_SET
; 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)
+; 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)
CenterMonName: ; 3ce9c (f:4e9c)
push de
inc hl
@@ -2204,7 +2208,8 @@
ld [wcc2d], a
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)
+; 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)
cp $1 ; was the item menu selected?
jr nz, .notItemMenu
; item menu was selected
@@ -3123,10 +3128,10 @@
jp z, ExecutePlayerMoveDone ; for selected move = FF, skip most of player's turn
xor a
ld [W_MOVEMISSED], a
- ld [wcced], a
- ld [wccf4], a
+ ld [wMonIsDisobedient], a
+ ld [wMoveDidntMiss], a
ld a, $a
- ld [wd05b], a
+ ld [wDamageMultipliers], a
ld a, [wcd6a]
and a
jp nz, ExecutePlayerMoveDone
@@ -3155,8 +3160,8 @@
PlayerCanExecuteChargingMove: ; 3d6a9 (f:56a9)
ld hl,W_PLAYERBATTSTATUS1
res ChargingUp,[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
+ ; 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]
PlayerCanExecuteMove: ; 3d6b0 (f:56b0)
call PrintMonName1Text
@@ -3183,30 +3188,30 @@
jp c,.moveHitTest ; SetDamageEffects moves (e.g. Seismic Toss and Super Fang) skip damage calculation
call CriticalHitTest
call HandleCounterMove
- jr z,asm_3d705
+ jr z,handleIfPlayerMoveMissed
call GetDamageVarsForPlayerAttack
call CalculateDamage
- jp z,asm_3d74b ; for moves with 0 BP, skip any further damage calculation and, for now, skip MoveHitTest
+ 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
call AdjustDamageForMoveType
call RandomizeDamage
.moveHitTest
call MoveHitTest
-asm_3d705
+handleIfPlayerMoveMissed
ld a,[W_MOVEMISSED]
and a
- jr z,asm_3d714
+ jr z,getPlayerAnimationType
ld a,[W_PLAYERMOVEEFFECT]
sub a,EXPLODE_EFFECT
- jr z,asm_3d71e ; don't play any animation if the move missed, unless it was EXPLODE_EFFECT
- jr asm_3d74b
-asm_3d714
+ jr z,playPlayerMoveAnimation ; don't play any animation if the move missed, unless it was EXPLODE_EFFECT
+ jr playerCheckIfFlyOrChargeEffect
+getPlayerAnimationType
ld a,[W_PLAYERMOVEEFFECT]
and a
- ld a,4
- jr z,asm_3d71e
- ld a,5
-asm_3d71e
+ ld a,4 ; move has no effect other than dealing damage
+ jr z,playPlayerMoveAnimation
+ ld a,5 ; move has effect
+playPlayerMoveAnimation
push af
ld a,[W_PLAYERBATTSTATUS2]
bit 4,a
@@ -3214,7 +3219,7 @@
ld b,BANK(Func_79747)
call nz,Bankswitch
pop af
- ld [wcc5b],a
+ ld [wAnimationType],a
ld a,[W_PLAYERMOVENUM]
call PlayMoveAnimation
call HandleExplodingAnimation
@@ -3225,7 +3230,7 @@
ld b,BANK(Func_79771)
call nz,Bankswitch
jr MirrorMoveCheck
-asm_3d74b
+playerCheckIfFlyOrChargeEffect
ld c,$1E
call DelayFrames
ld a,[W_PLAYERMOVEEFFECT]
@@ -3236,7 +3241,7 @@
jr MirrorMoveCheck
.playAnim
xor a
- ld [wcc5b],a
+ ld [wAnimationType],a
ld a,STATUS_AFFECTED_ANIM
call PlayMoveAnimation
MirrorMoveCheck
@@ -3246,7 +3251,7 @@
call MirrorMoveCopyMove
jp z,ExecutePlayerMoveDone
xor a
- ld [wcced],a
+ ld [wMonIsDisobedient],a
jp CheckIfPlayerNeedsToChargeUp ; if Mirror Move was successful go back to damage calculation for copied move
.metronomeCheck
cp a,METRONOME_EFFECT
@@ -3272,7 +3277,7 @@
call PrintCriticalOHKOText
callab DisplayEffectiveness
ld a,1
- ld [wccf4],a
+ ld [wMoveDidntMiss],a
.notDone
ld a,[W_PLAYERMOVEEFFECT]
ld hl,AlwaysHappenSideEffects
@@ -3292,8 +3297,8 @@
ld a,[wPlayerNumAttacksLeft]
dec a
ld [wPlayerNumAttacksLeft],a
- jp nz,asm_3d714 ; 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
+ 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 AttackingMultipleTimes,[hl] ; clear attacking multiple times status when all attacks are over
ld hl,MultiHitText
call PrintText
@@ -3307,9 +3312,9 @@
ld de,1
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's effect will be executed for a second time (although it's irrelevant).
- ; Includes side effects that only need to be called if the target didn't faint.
- ; Responsible for executing Twineedle's second effect (poison)
+ ; 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).
jp ExecutePlayerMoveDone
MultiHitText: ; 3d805 (f:5805)
@@ -3381,7 +3386,7 @@
jr z,.WakeUp ; if the number of turns hit 0, wake up
; fast asleep
xor a
- ld [wcc5b],a
+ ld [wAnimationType],a
ld a,SLP_ANIM - 1
call PlayMoveAnimation
ld hl,FastAsleepText
@@ -3465,7 +3470,7 @@
ld hl,IsConfusedText
call PrintText
xor a
- ld [wcc5b],a
+ ld [wAnimationType],a
ld a,CONF_ANIM - 1
call PlayMoveAnimation
call BattleRandom
@@ -3514,7 +3519,7 @@
.FlyOrChargeEffect
xor a
- ld [wcc5b],a
+ ld [wAnimationType],a
ld a,STATUS_AFFECTED_ANIM
call PlayMoveAnimation
.NotFlyOrChargeEffect
@@ -3568,7 +3573,7 @@
ld [hl],a
ld a,BIDE
ld [W_PLAYERMOVENUM],a
- ld hl,asm_3d705 ; skip damage calculation, DecrementPP and MoveHitTest
+ ld hl,handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest
jp .returnToHL
.ThrashingAboutCheck
@@ -3602,7 +3607,8 @@
ld a,[wPlayerNumAttacksLeft]
dec a ; did multi-turn move end?
ld [wPlayerNumAttacksLeft],a
- ld hl,asm_3d714 ; if it didn't, skip damage calculation (deal damage equal to last hit), DecrementPP and MoveHitTest
+ ld hl,getPlayerAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit),
+ ; DecrementPP and MoveHitTest
jp nz,.returnToHL
jp .returnToHL
@@ -3734,7 +3740,8 @@
xor a
ld [hl], a
call GetDamageVarsForPlayerAttack
- call CalculateDamage ; ignores AdjustDamageForMoveType (type-less damage), RandomizeDamage, and MoveHitTest (always hits)
+ call CalculateDamage ; ignores AdjustDamageForMoveType (type-less damage), RandomizeDamage,
+ ; and MoveHitTest (always hits)
pop af
pop hl
ld [hl], a
@@ -3744,7 +3751,7 @@
pop af
ld [hl], a
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
inc a
ld [H_WHOSETURN], a
call PlayMoveAnimation
@@ -3771,12 +3778,12 @@
ld [hl], a
ld [wd11e], a
call Func_3db85
- ld a, [wcced]
+ ld a, [wMonIsDisobedient]
and a
ld hl, Used2Text
ret nz
ld a, [wd11e]
- cp DOUBLESLAP
+ cp 3
ld hl, Used2Text
ret c
ld hl, Used1Text
@@ -3792,7 +3799,7 @@
db $08 ; asm
PrintInsteadText: ; 3db39 (f:5b39)
- ld a, [wcced]
+ ld a, [wMonIsDisobedient]
and a
jr z, PrintCF4BText
ld hl, InsteadText
@@ -3894,7 +3901,7 @@
ld de, W_ENEMYMOVEEFFECT
.playersTurn
ld hl, DoesntAffectMonText
- ld a, [wd05b]
+ ld a, [wDamageMultipliers]
and $7f
jr z, .gotTextToPrint
ld hl, AttackMissedText
@@ -3914,7 +3921,8 @@
; if you get here, the mon used jump kick or hi jump kick and missed
ld hl, W_DAMAGE ; since the move missed, W_DAMAGE will always contain 0 at this point.
- ; Thus, recoil damage will always be equal to 1 even if it was intended to be potential damage/8.
+ ; Thus, recoil damage will always be equal to 1
+ ; even if it was intended to be potential damage/8.
ld a, [hli]
ld b, [hl]
srl a
@@ -3999,7 +4007,7 @@
; stores whether the mon will use a move in Z flag
CheckForDisobedience: ; 3dc88 (f:5c88)
xor a
- ld [wcced], a
+ ld [wMonIsDisobedient], a
ld a, [wLinkState]
cp LINK_STATE_BATTLING
jr nz, .checkIfMonIsTraded
@@ -4140,7 +4148,7 @@
cp b
jr z, .monDoesNothing ; mon will not use move if only one move has remaining PP
ld a, $1
- ld [wcced], a
+ ld [wMonIsDisobedient], a
ld a, [wMaxMenuItem]
ld b, a
ld a, [wCurrentMenuItem]
@@ -4296,7 +4304,8 @@
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))
+ ld b, l ; b = player's offensive stat (possibly scaled)
+ ; (c already contains enemy's defensive stat (possibly scaled))
ld a, [wBattleMonLevel]
ld e, a ; e = level
ld a, [wCriticalHitOrOHKO]
@@ -4408,7 +4417,8 @@
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))
+ ld b, l ; b = enemy's offensive stat (possibly scaled)
+ ; (c already contains player's defensive stat (possibly scaled))
ld a, [wEnemyMonLevel]
ld e, a
ld a, [wCriticalHitOrOHKO]
@@ -4471,7 +4481,7 @@
; d: base power
; e: level
- ld a, [$fff3] ; whose turn?
+ ld a, [H_WHOSETURN] ; whose turn?
and a
ld a, [W_PLAYERMOVEEFFECT]
jr z, .effect
@@ -4494,7 +4504,7 @@
; Calculate OHKO damage based on remaining HP.
cp a, OHKO_EFFECT
- jp z, Func_3e016
+ jp z, JumpToOHKOMoveEffect
; Don't calculate damage for moves that don't do any.
ld a, d ; base power
@@ -4626,7 +4636,7 @@
and a
ret
-Func_3e016: ; 3e016 (f:6016)
+JumpToOHKOMoveEffect: ; 3e016 (f:6016)
call JumpMoveEffect
ld a, [W_MOVEMISSED]
dec a
@@ -5025,8 +5035,10 @@
AttackSubstitute: ; 3e25e (f:625e)
; 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.
-; If the user has a Substitute up and would take damage because of that, damage will be applied to the other player's Substitute.
-; Normal recoil such as from Double-Edge isn't affected by this glitch, because this function is never called in that case.
+; If the user has a Substitute up and would take damage because of that,
+; damage will be applied to the other player's Substitute.
+; Normal recoil such as from Double-Edge isn't affected by this glitch,
+; because this function is never called in that case.
ld hl,SubstituteTookDamageText
call PrintText
@@ -5050,10 +5062,11 @@
ld [de],a
ret nc
.substituteBroke
-; If the target's Substitute breaks, W_DAMAGE isn't updated with the amount of HP the Substitute had before being attacked.
+; If the target's Substitute breaks, W_DAMAGE isn't updated with the amount of HP
+; the Substitute had before being attacked.
ld h,b
ld l,c
- res 4,[hl] ; unset the substitute bit
+ res HasSubstituteUp,[hl] ; unset the substitute bit
ld hl,SubstituteBrokeText
call PrintText
; flip whose turn it is for the next function call
@@ -5185,7 +5198,7 @@
; function that picks a random move for metronome
MetronomePickMove: ; 3e348 (f:6348)
xor a
- ld [wcc5b],a
+ ld [wAnimationType],a
ld a,METRONOME
call PlayMoveAnimation ; play Metronome's animation
; values for player turn
@@ -5293,7 +5306,7 @@
ld [W_DAMAGE],a
ld a,l
ld [W_DAMAGE + 1],a
- ld hl,wd05b
+ ld hl,wDamageMultipliers
set 7,[hl]
.skipSameTypeAttackBonus
ld a,[wd11e]
@@ -5316,13 +5329,13 @@
push hl
push bc
inc hl
- ld a,[wd05b]
+ ld a,[wDamageMultipliers]
and a,$80
ld b,a
ld a,[hl] ; a = damage multiplier
ld [H_MULTIPLIER],a
add b
- ld [wd05b],a
+ ld [wDamageMultipliers],a
xor a
ld [H_MULTIPLICAND],a
ld hl,W_DAMAGE
@@ -5536,7 +5549,8 @@
.next
ld a,$0e
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)
+ 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)
; zero the high bytes of the multiplicand
xor a
ld [H_MULTIPLICAND],a
@@ -5545,7 +5559,8 @@
ld [H_MULTIPLICAND + 2],a ; set multiplicand to move accuracy
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
+; loop to do the calculations, the first iteration multiplies by the accuracy ratio and
+; the second iteration multiplies by the evasion ratio
.loop
push bc
ld hl, StatModifierRatios ; $76cb ; stat modifier ratios
@@ -5559,7 +5574,8 @@
ld [H_MULTIPLIER],a ; set multiplier to the numerator of the ratio
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 [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
call Divide
ld a,[H_QUOTIENT + 3]
@@ -5623,6 +5639,7 @@
ld [hl], a
ret
+; for more detailed commentary, see equivalent function for player side (ExecutePlayerMove)
ExecuteEnemyMove: ; 3e6bc (f:66bc)
ld a, [wEnemySelectedMove]
inc a
@@ -5639,13 +5656,13 @@
cp $4
ret nc
.executeEnemyMove
- ld hl, wccd5
+ ld hl, wAILayer2Encouragement
inc [hl]
xor a
ld [W_MOVEMISSED], a
- ld [wccf4], a
+ ld [wMoveDidntMiss], a
ld a, $a
- ld [wd05b], a
+ ld [wDamageMultipliers], a
call CheckEnemyStatusConditions
jr nz, .enemyHasNoSpecialConditions
jp [hl]
@@ -5677,7 +5694,7 @@
call CopyStringToCF4B
EnemyCanExecuteMove: ; 3e72b (f:672b)
xor a
- ld [wcced], a
+ ld [wMonIsDisobedient], a
call PrintMonName1Text
ld a, [W_ENEMYMOVEEFFECT]
ld hl, ResidualEffects1
@@ -5695,21 +5712,21 @@
ld hl, SetDamageEffects
ld de, $1
call IsInArray
- jp c, Func_3e77f
+ jp c, EnemyMoveHitTest
call CriticalHitTest
call HandleCounterMove
- jr z, asm_3e782
+ jr z, handleIfEnemyMoveMissed
call SwapPlayerAndEnemyLevels
call GetDamageVarsForEnemyAttack
call SwapPlayerAndEnemyLevels
call CalculateDamage
- jp z, Func_3e7d1
+ jp z, EnemyCheckIfFlyOrChargeEffect
call AdjustDamageForMoveType
call RandomizeDamage
-Func_3e77f: ; 3e77f (f:677f)
+EnemyMoveHitTest: ; 3e77f (f:677f)
call MoveHitTest
-asm_3e782: ; 3e782 (f:6782)
+handleIfEnemyMoveMissed: ; 3e782 (f:6782)
ld a, [W_MOVEMISSED]
and a
jr z, .asm_3e791
@@ -5716,21 +5733,21 @@
ld a, [W_ENEMYMOVEEFFECT]
cp EXPLODE_EFFECT
jr z, asm_3e7a0
- jr Func_3e7d1
+ jr EnemyCheckIfFlyOrChargeEffect
.asm_3e791
call SwapPlayerAndEnemyLevels
-Func_3e794: ; 3e794 (f:6794)
+GetEnemyAnimationType: ; 3e794 (f:6794)
ld a, [W_ENEMYMOVEEFFECT]
and a
ld a, $1
- jr z, asm_3e7a4
+ jr z, playEnemyMoveAnimation
ld a, $2
- jr asm_3e7a4
+ jr playEnemyMoveAnimation
asm_3e7a0: ; 3e7a0 (f:67a0)
call SwapPlayerAndEnemyLevels
xor a
-asm_3e7a4: ; 3e7a4 (f:67a4)
+playEnemyMoveAnimation: ; 3e7a4 (f:67a4)
push af
ld a, [W_ENEMYBATTSTATUS2]
bit HasSubstituteUp, a ; does mon have a substitute?
@@ -5738,7 +5755,7 @@
ld b, BANK(Func_79747)
call nz, Bankswitch
pop af
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a, [W_ENEMYMOVENUM]
call PlayMoveAnimation
call HandleExplodingAnimation
@@ -5748,24 +5765,24 @@
ld hl, Func_79771
ld b, BANK(Func_79771)
call nz, Bankswitch ; slide the substitute's sprite out
- jr asm_3e7ef
+ jr EnemyCheckIfMirrorMoveEffect
-Func_3e7d1: ; 3e7d1 (f:67d1)
+EnemyCheckIfFlyOrChargeEffect: ; 3e7d1 (f:67d1)
call SwapPlayerAndEnemyLevels
ld c, $1e
call DelayFrames
ld a, [W_ENEMYMOVEEFFECT]
cp FLY_EFFECT
- jr z, .asm_3e7e6
+ jr z, .playAnim
cp CHARGE_EFFECT
- jr z, .asm_3e7e6
- jr asm_3e7ef
-.asm_3e7e6
+ jr z, .playAnim
+ jr EnemyCheckIfMirrorMoveEffect
+.playAnim
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a,STATUS_AFFECTED_ANIM
call PlayMoveAnimation
-asm_3e7ef: ; 3e7ef (f:67ef)
+EnemyCheckIfMirrorMoveEffect: ; 3e7ef (f:67ef)
ld a, [W_ENEMYMOVEEFFECT]
cp MIRROR_MOVE_EFFECT
jr nz, .notMirrorMoveEffect
@@ -5796,7 +5813,7 @@
call PrintCriticalOHKOText
callab DisplayEffectiveness
ld a, 1
- ld [wccf4], a
+ ld [wMoveDidntMiss], a
.asm_3e83e
ld a, [W_ENEMYMOVEEFFECT]
ld hl, AlwaysHappenSideEffects
@@ -5816,7 +5833,7 @@
ld hl, wEnemyNumAttacksLeft
dec [hl]
pop hl
- jp nz, Func_3e794
+ jp nz, GetEnemyAnimationType
res AttackingMultipleTimes, [hl] ; mon is no longer hitting multiple times
ld hl, HitXTimesText
call PrintText
@@ -5854,7 +5871,7 @@
ld hl, FastAsleepText
call PrintText
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a,SLP_ANIM
call PlayMoveAnimation
jr .next1
@@ -5930,7 +5947,7 @@
ld hl, IsConfusedText
call PrintText
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a,CONF_ANIM
call PlayMoveAnimation
call BattleRandom
@@ -5973,7 +5990,7 @@
pop af
ld [hl], a
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld [H_WHOSETURN], a
ld a, POUND
call PlayMoveAnimation
@@ -6014,7 +6031,7 @@
jr .notFlyOrChargeEffect
.flyOrChargeEffect
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a, STATUS_AFFECTED_ANIM
call PlayMoveAnimation
.notFlyOrChargeEffect
@@ -6068,7 +6085,7 @@
ld a, BIDE
ld [W_ENEMYMOVENUM], a
call SwapPlayerAndEnemyLevels
- ld hl, asm_3e782
+ ld hl, handleIfEnemyMoveMissed
jp .enemyReturnToHL
.checkIfThrashingAbout
bit ThrashingAbout, [hl] ; is mon using thrash or petal dance?
@@ -6099,7 +6116,7 @@
call PrintText
ld hl, wEnemyNumAttacksLeft
dec [hl]
- ld hl, Func_3e794
+ ld hl, GetEnemyAnimationType
jp nz, .enemyReturnToHL
jp .enemyReturnToHL
.checkIfUsingRage
@@ -6787,7 +6804,7 @@
and a
ret nz
ld a, 5
- ld [wcc5b], a
+ ld [wAnimationType], a
PlayMoveAnimation: ; 3ef07 (f:6f07)
ld [W_ANIMATIONID],a
@@ -6955,6 +6972,7 @@
ld c, a
jp LoadUncompressedSpriteData
+; unreferenced
Func_3f069: ; 3f069 (f:7069)
xor a
ld [wc0f1], a
@@ -7030,6 +7048,7 @@
dec b
jr nz, .asm_3f0de
ret
+
.asm_3f0ed
push bc
ld b, $0
@@ -7053,7 +7072,7 @@
jr nz, .asm_3f0f4
ret
-LoadMonBackPic:
+LoadMonBackPic: ; 3f103 (f:7103)
; Assumes the monster's attributes have
; been loaded with GetMonHeader.
ld a, [wBattleMonSpecies2]
@@ -7080,14 +7099,14 @@
ret
_JumpMoveEffect: ; 3f138 (f:7138)
- ld a, [$fff3] ;whose turn?
+ ld a, [H_WHOSETURN]
and a
ld a, [W_PLAYERMOVEEFFECT]
jr z, .next1
ld a, [W_ENEMYMOVEEFFECT]
.next1
- dec a ;subtract 1, there is no special effect for 00
- add a ;x2, 16bit pointers
+ dec a ; subtract 1, there is no special effect for 00
+ add a ; x2, 16bit pointers
ld hl, MoveEffectPointerTable
ld b, 0
ld c, a
@@ -7095,7 +7114,7 @@
ld a, [hli]
ld h, [hl]
ld l, a
- jp [hl] ;jump to special effect handler
+ jp [hl] ; jump to special effect handler
MoveEffectPointerTable: ; 3f150 (f:7150)
dw SleepEffect ; unused effect
@@ -7223,7 +7242,7 @@
and $7
jr z, .setSleepCounter
ld [de], a
- call Func_3fb89
+ call PlayCurrentMoveAnimation2
ld hl, FellAsleepText
jp PrintText
.didntAffect
@@ -7309,10 +7328,10 @@
cp POISON_EFFECT
jr z, .asm_3f2cd
ld a, b
- call Func_3fb96
+ call PlayBattleAnimation2
jp PrintText
.asm_3f2cd
- call Func_3fb89
+ call PlayCurrentMoveAnimation2
jp PrintText
.noEffect
ld a, [de]
@@ -7357,10 +7376,10 @@
FreezeBurnParalyzeEffect: ; 3f30c (f:730c)
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
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
- ld a, [$fff3]
+ ld a, [H_WHOSETURN]
and a
jp nz, opponentAttacker
ld a, [wEnemyMonStatus]
@@ -7472,7 +7491,7 @@
; any fire-type move that has a chance inflict burn (all but Fire Spin) will defrost a frozen target
and a, 1 << FRZ ; are they frozen?
ret z ; return if so
- ld a, [$fff3]
+ ld a, [H_WHOSETURN]
and a
jr nz, .opponent
;player [attacker]
@@ -7568,7 +7587,7 @@
jr nz, .recalculateStat
ld a, [hl]
sbc 999 / $100
- jp z, Func_3f520
+ jp z, RestoreOriginalStatModifier
.recalculateStat ; recalculate affected stat
; paralysis and burn penalties, as well as badge boosts are ignored
push hl
@@ -7661,7 +7680,7 @@
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
-Func_3f520: ; 3f520 (f:7520)
+RestoreOriginalStatModifier: ; 3f520 (f:7520)
pop hl
dec [hl]
@@ -7838,7 +7857,7 @@
ld a, [de]
cp $44
jr nc, .ApplyBadgeBoostsAndStatusPenalties
- call Func_3fb89
+ call PlayCurrentMoveAnimation2
.ApplyBadgeBoostsAndStatusPenalties
ld a, [H_WHOSETURN]
and a
@@ -7869,7 +7888,7 @@
ld a, [de]
cp $44
ret nc
- jp Func_3fb4e
+ jp ConditionalPrintButItFailed
MonsStatsFellText: ; 3f661 (f:7661)
TX_FAR _MonsStatsFellText
@@ -7961,7 +7980,7 @@
ld [bc], a ; set Bide counter to 2 or 3 at random
ld a, [H_WHOSETURN]
add XSTATITEM_ANIM
- jp Func_3fb96
+ jp PlayBattleAnimation2
ThrashPetalDanceEffect: ; 3f717 (f:7717)
ld hl, W_PLAYERBATTSTATUS1
@@ -7980,7 +7999,7 @@
ld [de], a ; set thrash/petal dance counter to 2 or 3 at random
ld a, [H_WHOSETURN]
add ANIM_B0
- jp Func_3fb96
+ jp PlayBattleAnimation2
SwitchAndTeleportEffect: ; 3f739 (f:7739)
ld a, [H_WHOSETURN]
@@ -8014,7 +8033,7 @@
.asm_3f76e
call ReadPlayerMonCurHPAndStatus
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
inc a
ld [wEscapedFromBattle], a
ld a, [W_PLAYERMOVENUM]
@@ -8056,7 +8075,7 @@
.asm_3f7c1
call ReadPlayerMonCurHPAndStatus
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
inc a
ld [wEscapedFromBattle], a
ld a, [W_ENEMYMOVENUM]
@@ -8068,7 +8087,7 @@
ld a, [W_ENEMYMOVENUM]
cp TELEPORT
jp nz, PrintText
- jp Func_3fb4e
+ jp ConditionalPrintButItFailed
.asm_3f7e4
push af
call PlayBattleAnimation
@@ -8197,7 +8216,7 @@
ld b, ANIM_C0
.notDigOrFly
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a, b
call PlayBattleAnimation
ld a, [de]
@@ -8329,7 +8348,7 @@
ld [bc], a ; confusion status will last 2-5 turns
pop af
cp CONFUSION_SIDE_EFFECT
- call nz, Func_3fb89
+ call nz, PlayCurrentMoveAnimation2
ld hl, BecameConfusedText
jp PrintText
@@ -8342,7 +8361,7 @@
ret z
ld c, $32
call DelayFrames
- jp Func_3fb4e
+ jp ConditionalPrintButItFailed
ParalyzeEffect: ; 3f9b1 (f:79b1)
ld hl, ParalyzeEffect_
@@ -8350,8 +8369,8 @@
jp Bankswitch
SubstituteEffect: ; 3f9b9 (f:79b9)
- ld hl, SubstituteEffectHandler
- ld b, BANK(SubstituteEffectHandler)
+ ld hl, SubstituteEffect_
+ ld b, BANK(SubstituteEffect_)
jp Bankswitch
HyperBeamEffect: ; 3f9c1 (f:79c1)
@@ -8534,7 +8553,7 @@
swap c
add c
ld [de], a
- call Func_3fb89
+ call PlayCurrentMoveAnimation2
ld hl, wccee
ld a, [H_WHOSETURN]
and a
@@ -8597,10 +8616,10 @@
TX_FAR _NoEffectText
db "@"
-Func_3fb4e: ; 3fb4e (f:7b4e)
- ld a, [wccf4]
+ConditionalPrintButItFailed: ; 3fb4e (f:7b4e)
+ ld a, [wMoveDidntMiss]
and a
- ret nz
+ ret nz ; return if the side effect failed, yet the attack was successful
PrintButItFailedText_: ; 3fb53 (f:7b53)
ld hl, ButItFailedText
@@ -8642,30 +8661,35 @@
pop hl
ret
-Func_3fb89: ; 3fb89 (f:7b89)
+PlayCurrentMoveAnimation2: ; 3fb89 (f:7b89)
+; animation at MOVENUM will be played unless MOVENUM is 0
+; plays wAnimationType 3 or 6
ld a, [H_WHOSETURN]
and a
ld a, [W_PLAYERMOVENUM]
- jr z, .asm_3fb94
+ jr z, .notEnemyTurn
ld a, [W_ENEMYMOVENUM]
-.asm_3fb94
+.notEnemyTurn
and a
ret z
-Func_3fb96: ; 3fb96 (f:7b96)
+PlayBattleAnimation2: ; 3fb96 (f:7b96)
+; play animation ID at a and animation type 6 or 3
ld [W_ANIMATIONID], a
ld a, [H_WHOSETURN]
and a
ld a, $6
- jr z, .asm_3fba2
+ jr z, .storeAnimationType
ld a, $3
-.asm_3fba2
- ld [wcc5b], a
- jp Func_3fbbc
+.storeAnimationType
+ ld [wAnimationType], a
+ jp PlayBattleAnimationGotID
PlayCurrentMoveAnimation: ; 3fba8 (f:7ba8)
+; animation at MOVENUM will be played unless MOVENUM is 0
+; resets wAnimationType
xor a
- ld [wcc5b], a
+ ld [wAnimationType], a
ld a, [H_WHOSETURN]
and a
ld a, [W_PLAYERMOVENUM]
@@ -8676,9 +8700,11 @@
ret z
PlayBattleAnimation: ; 3fbb9 (f:7bb9)
+; play animation ID at a and predefined animation type
ld [W_ANIMATIONID], a
-Func_3fbbc: ; 3fbbc (f:7bbc)
+PlayBattleAnimationGotID: ; 3fbbc (f:7bbc)
+; play animation at W_ANIMATIONID
push hl
push de
push bc
--- a/engine/battle/d.asm
+++ /dev/null
@@ -1,23 +1,0 @@
-; display "[player] VS [enemy]" text box with pokeballs representing their parties next to the names
-DisplayLinkBattleVersusTextBox: ; 372d6 (d:72d6)
- call LoadTextBoxTilePatterns
- hlCoord 3, 4
- ld b, $7
- ld c, $c
- call TextBoxBorder
- hlCoord 4, 5
- ld de, wPlayerName
- call PlaceString
- hlCoord 4, 10
- ld de, wLinkEnemyTrainerName
- call PlaceString
-; place bold "VS" tiles between the names
- hlCoord 9, 8
- ld a, $69
- ld [hli], a
- ld [hl], $6a
- xor a
- ld [wUpdateSpritesEnabled], a
- callab SetupPlayerAndEnemyPokeballs
- ld c, 150
- jp DelayFrames
--- /dev/null
+++ b/engine/battle/decrement_pp.asm
@@ -1,0 +1,43 @@
+DecrementPP: ; 68000 (1a:4000)
+; after using a move, decrement pp in battle and (if not transformed?) in party
+ ld a, [de]
+ cp a, STRUGGLE
+ ret z ; if the pokemon is using "struggle", there's nothing to do
+ ; we don't decrement PP for "struggle"
+ ld hl, W_PLAYERBATTSTATUS1
+ ld a, [hli] ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the
+ ; W_PLAYERBATTSTATUS2 status flags later
+ and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes)
+ ret nz ; if any of these statuses are true, don't decrement PP
+ bit UsingRage, [hl]
+ ret nz ; don't decrement PP either if Pokemon is using Rage
+ ld hl, wBattleMonPP ; PP of first move (in battle)
+
+; decrement PP in the battle struct
+ call .DecrementPP
+
+; decrement PP in the party struct
+ ld a, [W_PLAYERBATTSTATUS3]
+ bit Transformed, a
+ ret nz ; Return if transformed. Pokemon Red stores the "current pokemon's" PP
+ ; separately from the "Pokemon in your party's" PP. This is
+ ; duplication -- in all cases *other* than Pokemon with Transform.
+ ; Normally, this means we have to go on and make the same
+ ; modification to the "party's pokemon" PP that we made to the
+ ; "current pokemon's" PP. But, if we're dealing with a Transformed
+ ; Pokemon, it has separate PP for the move set that it copied from
+ ; its opponent, which is *not* the same as its real PP as part of your
+ ; party. So we return, and don't do that part.
+
+ ld hl, wPartyMon1PP ; PP of first move (in party)
+ ld a, [wPlayerMonNumber] ; which mon in party is active
+ ld bc, wPartyMon2 - wPartyMon1
+ call AddNTimes ; calculate address of the mon to modify
+.DecrementPP
+ ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use?
+ ld c, a
+ ld b, 0
+ add hl ,bc ; calculate the address in memory of the PP we need to decrement
+ ; based on the move chosen.
+ dec [hl] ; Decrement PP
+ ret
--- /dev/null
+++ b/engine/battle/display_effectiveness.asm
@@ -1,0 +1,18 @@
+DisplayEffectiveness: ; 2fb7b (b:7b7b)
+ ld a, [wDamageMultipliers]
+ and a, $7F
+ cp a, $0A
+ ret z
+ ld hl, SuperEffectiveText
+ jr nc, .done
+ ld hl, NotVeryEffectiveText
+.done
+ jp PrintText
+
+SuperEffectiveText: ; 2fb8e (b:7b8e)
+ TX_FAR _SuperEffectiveText
+ db "@"
+
+NotVeryEffectiveText: ; 2fb93 (b:7b93)
+ TX_FAR _NotVeryEffectiveText
+ db "@"
--- /dev/null
+++ b/engine/battle/draw_hud_pokeball_gfx.asm
@@ -1,0 +1,191 @@
+DrawAllPokeballs: ; 3a849 (e:6849)
+ call LoadPartyPokeballGfx
+ call SetupOwnPartyPokeballs
+ ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+ dec a
+ ret z ; return if wild pokémon
+ jp SetupEnemyPartyPokeballs
+
+DrawEnemyPokeballs: ; 0x3a857
+ call LoadPartyPokeballGfx
+ jp SetupEnemyPartyPokeballs
+
+LoadPartyPokeballGfx: ; 3a85d (e:685d)
+ ld de, PokeballTileGraphics ; $697e
+ ld hl, vSprites + $310
+ ld bc, (BANK(PokeballTileGraphics) << 8) + $04
+ jp CopyVideoData
+
+SetupOwnPartyPokeballs: ; 3a869 (e:6869)
+ call PlacePlayerHUDTiles
+ ld hl, wPartyMon1
+ ld de, wPartyCount ; wPartyCount
+ call SetupPokeballs
+ ld a, $60
+ ld hl, W_BASECOORDX ; wd081
+ ld [hli], a
+ ld [hl], a
+ ld a, $8
+ ld [wTrainerEngageDistance], a
+ ld hl, wOAMBuffer
+ jp WritePokeballOAMData
+
+SetupEnemyPartyPokeballs: ; 3a887 (e:6887)
+ call PlaceEnemyHUDTiles
+ ld hl, wEnemyMons
+ ld de, wEnemyPartyCount ; wEnemyPartyCount
+ call SetupPokeballs
+ ld hl, W_BASECOORDX ; wd081
+ ld a, $48
+ ld [hli], a
+ ld [hl], $20
+ ld a, $f8
+ ld [wTrainerEngageDistance], a
+ ld hl, wOAMBuffer + PARTY_LENGTH * 4
+ jp WritePokeballOAMData
+
+SetupPokeballs: ; 0x3a8a6
+ ld a, [de]
+ push af
+ ld de, wBuffer
+ ld c, PARTY_LENGTH
+ ld a, $34 ; empty pokeball
+.emptyloop
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .emptyloop
+ pop af
+ ld de, wBuffer
+.monloop
+ push af
+ call PickPokeball
+ inc de
+ pop af
+ dec a
+ jr nz, .monloop
+ ret
+
+PickPokeball: ; 3a8c2 (e:68c2)
+ inc hl
+ ld a, [hli]
+ and a
+ jr nz, .alive
+ ld a, [hl]
+ and a
+ ld b, $33 ; crossed ball (fainted)
+ jr z, .done_fainted
+.alive
+ inc hl
+ inc hl
+ ld a, [hl] ; status
+ and a
+ ld b, $32 ; black ball (status)
+ jr nz, .done
+ dec b ; regular ball
+ jr .done
+.done_fainted
+ inc hl
+ inc hl
+.done
+ ld a, b
+ ld [de], a
+ ld bc, $0028 ; rest of mon struct
+ add hl, bc
+ ret
+
+WritePokeballOAMData: ; 3a8e1 (e:68e1)
+ ld de, wBuffer
+ ld c, PARTY_LENGTH
+.loop
+ ld a, [W_BASECOORDY] ; wd082
+ ld [hli], a
+ ld a, [W_BASECOORDX] ; wd081
+ ld [hli], a
+ ld a, [de]
+ ld [hli], a
+ xor a
+ ld [hli], a
+ ld a, [W_BASECOORDX] ; wd081
+ ld b, a
+ ld a, [wTrainerEngageDistance]
+ add b
+ ld [W_BASECOORDX], a ; wd081
+ inc de
+ dec c
+ jr nz, .loop
+ ret
+
+PlacePlayerHUDTiles: ; 3a902 (e:6902)
+ ld hl, PlayerBattleHUDGraphicsTiles ; $6916
+ ld de, wTrainerFacingDirection
+ ld bc, $3
+ call CopyData
+ hlCoord 18, 10
+ ld de, rIE ; $ffff
+ jr PlaceHUDTiles
+
+PlayerBattleHUDGraphicsTiles: ; 3a916 (e:6916)
+; The tile numbers for specific parts of the battle display for the player's pokemon
+ db $73 ; unused ($73 is hardcoded into the routine that uses these bytes)
+ db $77 ; lower-right corner tile of the HUD
+ db $6F ; lower-left triangle tile of the HUD
+
+PlaceEnemyHUDTiles: ; 3a919 (e:6919)
+ ld hl, EnemyBattleHUDGraphicsTiles ; $692d
+ ld de, wTrainerFacingDirection
+ ld bc, $3
+ call CopyData
+ hlCoord 1, 2
+ ld de, $1
+ jr PlaceHUDTiles
+
+EnemyBattleHUDGraphicsTiles: ; 3a92d (e:692d)
+; The tile numbers for specific parts of the battle display for the enemy
+ db $73 ; unused ($73 is hardcoded in the routine that uses these bytes)
+ db $74 ; lower-left corner tile of the HUD
+ db $78 ; lower-right triangle tile of the HUD
+
+PlaceHUDTiles: ; 3a930 (e:6930)
+ ld [hl], $73
+ ld bc, $14
+ add hl, bc
+ ld a, [wTrainerScreenY]
+ ld [hl], a
+ ld a, $8
+.asm_3a93c
+ add hl, de
+ ld [hl], $76
+ dec a
+ jr nz, .asm_3a93c
+ add hl, de
+ ld a, [wTrainerScreenX]
+ ld [hl], a
+ ret
+
+SetupPlayerAndEnemyPokeballs: ; 3a948 (e:6948)
+ call LoadPartyPokeballGfx
+ ld hl, wPartyMon1Species ; wPartyMon1Species (aliases: wPartyMon1)
+ ld de, wPartyCount ; wPartyCount
+ call SetupPokeballs
+ ld hl, W_BASECOORDX ; wd081
+ ld a, $50
+ ld [hli], a
+ ld [hl], $40
+ ld a, $8
+ ld [wTrainerEngageDistance], a
+ ld hl, wOAMBuffer
+ call WritePokeballOAMData
+ ld hl, wEnemyMons ; wEnemyMon1Species
+ ld de, wEnemyPartyCount ; wEnemyPartyCount
+ call SetupPokeballs
+ ld hl, W_BASECOORDX ; wd081
+ ld a, $50
+ ld [hli], a
+ ld [hl], $68
+ ld hl, wOAMBuffer + $18
+ jp WritePokeballOAMData
+
+; four tiles: pokeball, black pokeball (status ailment), crossed out pokeball (faited) and pokeball slot (no mon)
+PokeballTileGraphics:: ; 3a97e (e:697e)
+ INCBIN "gfx/pokeball.2bpp"
--- a/engine/battle/e.asm
+++ /dev/null
@@ -1,1565 +1,0 @@
-; does nothing since no stats are ever selected (barring glitches)
-DoubleSelectedStats: ; 39680 (e:5680)
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerStatsToDouble]
- ld hl, wBattleMonAttack + 1
- jr z, .notEnemyTurn
- ld a, [wEnemyStatsToDouble]
- ld hl, wEnemyMonAttack + 1
-.notEnemyTurn
- ld c, 4
- ld b, a
-.loop
- srl b
- call c, .doubleStat
- inc hl
- inc hl
- dec c
- ret z
- jr .loop
-
-.doubleStat
- ld a, [hl]
- add a
- ld [hld], a
- ld a, [hl]
- rl a
- ld [hli], a
- ret
-
-; does nothing since no stats are ever selected (barring glitches)
-HalveSelectedStats: ; 396a7 (e:56a7)
- ld a, [H_WHOSETURN]
- and a
- ld a, [wPlayerStatsToHalve]
- ld hl, wBattleMonAttack
- jr z, .notEnemyTurn
- ld a, [wEnemyStatsToHalve]
- ld hl, wEnemyMonAttack
-.notEnemyTurn
- ld c, 4
- ld b, a
-.loop
- srl b
- call c, .halveStat
- inc hl
- inc hl
- dec c
- ret z
- jr .loop
-
-.halveStat
- ld a, [hl]
- srl a
- ld [hli], a
- rr [hl]
- or [hl]
- jr nz, .nonzeroStat
- ld [hl], 1
-.nonzeroStat
- dec hl
- ret
-
-_ScrollTrainerPicAfterBattle: ; 396d3 (e:56d3)
-; Load the enemy trainer's pic and scrolls it into
-; the screen from the right.
- xor a
- ld [wEnemyMonSpecies2], a
- ld b, $1
- call GoPAL_SET
- callab _LoadTrainerPic
- hlCoord 19, 0
- ld c, $0
-.scrollLoop
- inc c
- ld a, c
- cp 7
- ret z
- ld d, $0
- push bc
- push hl
-.drawTrainerPicLoop
- call DrawTrainerPicColumn
- inc hl
- ld a, 7
- add d
- ld d, a
- dec c
- jr nz, .drawTrainerPicLoop
- ld c, 4
- call DelayFrames
- pop hl
- pop bc
- dec hl
- jr .scrollLoop
-
-; write one 7-tile column of the trainer pic to the tilemap
-DrawTrainerPicColumn: ; 39707 (e:5707)
- push hl
- push de
- push bc
- ld e, 7
-.loop
- ld [hl], d
- ld bc, SCREEN_WIDTH
- add hl, bc
- inc d
- dec e
- jr nz, .loop
- pop bc
- pop de
- pop hl
- ret
-
-; creates a set of moves that may be used and returns its address in hl
-; unused slots are filled with 0, all used slots may be chosen with equal probability
-AIEnemyTrainerChooseMoves: ; 39719 (e:5719)
- ld a, $a
- ld hl, wHPBarMaxHP ; init temporary move selection array. Only the moves with the lowest numbers are chosen in the end
- ld [hli], a ; move 1
- ld [hli], a ; move 2
- ld [hli], a ; move 3
- ld [hl], a ; move 4
- ld a, [W_ENEMYDISABLEDMOVE] ; forbid disabled move (if any)
- swap a
- and $f
- jr z, .noMoveDisabled
- ld hl, wHPBarMaxHP
- dec a
- ld c, a
- ld b, $0
- add hl, bc ; advance pointer to forbidden move
- ld [hl], $50 ; forbid (highly discourage) disabled move
-.noMoveDisabled
- ld hl, TrainerClassMoveChoiceModifications ; 589B
- ld a, [W_TRAINERCLASS]
- ld b, a
-.loopTrainerClasses
- dec b
- jr z, .readTrainerClassData
-.loopTrainerClassData
- ld a, [hli]
- and a
- jr nz, .loopTrainerClassData
- jr .loopTrainerClasses
-.readTrainerClassData
- ld a, [hl]
- and a
- jp z, .useOriginalMoveSet
- push hl
-.nextMoveChoiceModification
- pop hl
- ld a, [hli]
- and a
- jr z, .loopFindMinimumEntries
- push hl
- ld hl, AIMoveChoiceModificationFunctionPointers ; $57a3
- dec a
- add a
- ld c, a
- ld b, $0
- add hl, bc ; skip to pointer
- ld a, [hli] ; read pointer into hl
- ld h, [hl]
- ld l, a
- ld de, .nextMoveChoiceModification ; set return address
- push de
- jp [hl] ; execute modification function
-.loopFindMinimumEntries ; all entries will be decremented sequentially until one of them is zero
- ld hl, wHPBarMaxHP ; temp move selection array
- ld de, wEnemyMonMoves ; enemy moves
- ld c, $4
-.loopDecrementEntries
- ld a, [de]
- inc de
- and a
- jr z, .loopFindMinimumEntries
- dec [hl]
- jr z, .minimumEntriesFound
- inc hl
- dec c
- jr z, .loopFindMinimumEntries
- jr .loopDecrementEntries
-.minimumEntriesFound
- ld a, c
-.loopUndoPartialIteration ; undo last (partial) loop iteration
- inc [hl]
- dec hl
- inc a
- cp $5
- jr nz, .loopUndoPartialIteration
- ld hl, wHPBarMaxHP ; temp move selection array
- ld de, wEnemyMonMoves ; enemy moves
- ld c, $4
-.filterMinimalEntries ; all minimal entries now have value 1. All other slots will be disabled (move set to 0)
- ld a, [de]
- and a
- jr nz, .moveExisting ; 0x3978a $1
- ld [hl], a
-.moveExisting
- ld a, [hl]
- dec a
- jr z, .slotWithMinimalValue
- xor a
- ld [hli], a ; disable move slot
- jr .next
-.slotWithMinimalValue
- ld a, [de]
- ld [hli], a ; enable move slot
-.next
- inc de
- dec c
- jr nz, .filterMinimalEntries
- ld hl, wHPBarMaxHP ; use created temporary array as move set
- ret
-.useOriginalMoveSet
- ld hl, wEnemyMonMoves ; use original move set
- ret
-
-AIMoveChoiceModificationFunctionPointers: ; 397a3 (e:57a3)
- dw AIMoveChoiceModification1
- dw AIMoveChoiceModification2
- dw AIMoveChoiceModification3
- dw AIMoveChoiceModification4 ; unused, does nothing
-
-; discourages moves that cause no damage but only a status ailment if player's mon already has one
-AIMoveChoiceModification1: ; 397ab (e:57ab)
- ld a, [wBattleMonStatus]
- and a
- ret z ; return if no status ailment on player's mon
- ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest)
- ld de, wEnemyMonMoves ; enemy moves
- ld b, $5
-.nextMove
- dec b
- ret z ; processed all 4 moves
- inc hl
- ld a, [de]
- and a
- ret z ; no more moves in move set
- inc de
- call ReadMove
- ld a, [W_ENEMYMOVEPOWER]
- and a
- jr nz, .nextMove
- ld a, [W_ENEMYMOVEEFFECT]
- push hl
- push de
- push bc
- ld hl, StatusAilmentMoveEffects
- ld de, $0001
- call IsInArray
- pop bc
- pop de
- pop hl
- jr nc, .nextMove
- ld a, [hl]
- add $5 ; discourage move
- ld [hl], a
- jr .nextMove
-
-StatusAilmentMoveEffects ; 57e2
- db $01 ; some sleep effect?
- db SLEEP_EFFECT
- db POISON_EFFECT
- db PARALYZE_EFFECT
- db $FF
-
-; slightly encourage moves with specific effects
-AIMoveChoiceModification2: ; 397e7 (e:57e7)
- ld a, [wccd5]
- cp $1
- ret nz
- ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest)
- ld de, wEnemyMonMoves ; enemy moves
- ld b, $5
-.nextMove
- dec b
- ret z ; processed all 4 moves
- inc hl
- ld a, [de]
- and a
- ret z ; no more moves in move set
- inc de
- call ReadMove
- ld a, [W_ENEMYMOVEEFFECT]
- cp ATTACK_UP1_EFFECT
- jr c, .nextMove
- cp BIDE_EFFECT
- jr c, .preferMove
- cp ATTACK_UP2_EFFECT
- jr c, .nextMove
- cp POISON_EFFECT
- jr c, .preferMove
- jr .nextMove
-.preferMove
- dec [hl] ; slighly encourage this move
- jr .nextMove
-
-; encourages moves that are effective against the player's mon
-AIMoveChoiceModification3: ; 39817 (e:5817)
- ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest)
- ld de, wEnemyMonMoves ; enemy moves
- ld b, $5
-.nextMove
- dec b
- ret z ; processed all 4 moves
- inc hl
- ld a, [de]
- and a
- ret z ; no more moves in move set
- inc de
- call ReadMove
- push hl
- push bc
- push de
- callab AIGetTypeEffectiveness
- pop de
- pop bc
- pop hl
- ld a, [wd11e]
- cp $10
- jr z, .nextMove
- jr c, .notEffectiveMove
- dec [hl] ; slighly encourage this move
- jr .nextMove
-.notEffectiveMove ; discourages non-effective moves if better moves are available
- push hl
- push de
- push bc
- ld a, [W_ENEMYMOVETYPE]
- ld d, a
- ld hl, wEnemyMonMoves ; enemy moves
- ld b, $5
- ld c, $0
-.loopMoves
- dec b
- jr z, .done
- ld a, [hli]
- and a
- jr z, .done
- call ReadMove
- ld a, [W_ENEMYMOVEEFFECT]
- cp SUPER_FANG_EFFECT
- jr z, .betterMoveFound ; Super Fang is considered to be a better move
- cp SPECIAL_DAMAGE_EFFECT
- jr z, .betterMoveFound ; any special damage moves are considered to be better moves
- cp FLY_EFFECT
- jr z, .betterMoveFound ; Fly is considered to be a better move
- ld a, [W_ENEMYMOVETYPE]
- cp d
- jr z, .loopMoves
- ld a, [W_ENEMYMOVEPOWER]
- and a
- jr nz, .betterMoveFound ; damaging moves of a different type are considered to be better moves
- jr .loopMoves
-.betterMoveFound
- ld c, a
-.done
- ld a, c
- pop bc
- pop de
- pop hl
- and a
- jr z, .nextMove
- inc [hl] ; slighly discourage this move
- jr .nextMove
-AIMoveChoiceModification4: ; 39883 (e:5883)
- ret
-
-ReadMove: ; 39884 (e:5884)
- push hl
- push de
- push bc
- dec a
- ld hl,Moves
- ld bc,6
- call AddNTimes
- ld de,W_ENEMYMOVENUM
- call CopyData
- pop bc
- pop de
- pop hl
- ret
-
-; move choice modification methods that are applied for each trainer class
-; 0 is sentinel value
-TrainerClassMoveChoiceModifications: ; 3989b (e:589b)
- db 0 ; YOUNGSTER
- db 1,0 ; BUG CATCHER
- db 1,0 ; LASS
- db 1,3,0 ; SAILOR
- db 1,0 ; JR__TRAINER_M
- db 1,0 ; JR__TRAINER_F
- db 1,2,3,0; POKEMANIAC
- db 1,2,0 ; SUPER_NERD
- db 1,0 ; HIKER
- db 1,0 ; BIKER
- db 1,3,0 ; BURGLAR
- db 1,0 ; ENGINEER
- db 1,2,0 ; JUGGLER_X
- db 1,3,0 ; FISHER
- db 1,3,0 ; SWIMMER
- db 0 ; CUE_BALL
- db 1,0 ; GAMBLER
- db 1,3,0 ; BEAUTY
- db 1,2,0 ; PSYCHIC_TR
- db 1,3,0 ; ROCKER
- db 1,0 ; JUGGLER
- db 1,0 ; TAMER
- db 1,0 ; BIRD_KEEPER
- db 1,0 ; BLACKBELT
- db 1,0 ; SONY1
- db 1,3,0 ; PROF_OAK
- db 1,2,0 ; CHIEF
- db 1,2,0 ; SCIENTIST
- db 1,3,0 ; GIOVANNI
- db 1,0 ; ROCKET
- db 1,3,0 ; COOLTRAINER_M
- db 1,3,0 ; COOLTRAINER_F
- db 1,0 ; BRUNO
- db 1,0 ; BROCK
- db 1,3,0 ; MISTY
- db 1,3,0 ; LT__SURGE
- db 1,3,0 ; ERIKA
- db 1,3,0 ; KOGA
- db 1,3,0 ; BLAINE
- db 1,3,0 ; SABRINA
- db 1,2,0 ; GENTLEMAN
- db 1,3,0 ; SONY2
- db 1,3,0 ; SONY3
- db 1,2,3,0; LORELEI
- db 1,0 ; CHANNELER
- db 1,0 ; AGATHA
- db 1,3,0 ; LANCE
-
-TrainerPicAndMoneyPointers: ; 39914 (e:5914)
-; trainer pic pointers and base money.
-; money received after battle = base money × level of highest-level enemy mon
- dw YoungsterPic
- money 1500
-
- dw BugCatcherPic
- money 1000
-
- dw LassPic
- money 1500
-
- dw SailorPic
- money 3000
-
- dw JrTrainerMPic
- money 2000
-
- dw JrTrainerFPic
- money 2000
-
- dw PokemaniacPic
- money 5000
-
- dw SuperNerdPic
- money 2500
-
- dw HikerPic
- money 3500
-
- dw BikerPic
- money 2000
-
- dw BurglarPic
- money 9000
-
- dw EngineerPic
- money 5000
-
- dw JugglerPic
- money 3500
-
- dw FisherPic
- money 3500
-
- dw SwimmerPic
- money 500
-
- dw CueBallPic
- money 2500
-
- dw GamblerPic
- money 7000
-
- dw BeautyPic
- money 7000
-
- dw PsychicPic
- money 1000
-
- dw RockerPic
- money 2500
-
- dw JugglerPic
- money 3500
-
- dw TamerPic
- money 4000
-
- dw BirdKeeperPic
- money 2500
-
- dw BlackbeltPic
- money 2500
-
- dw Rival1Pic
- money 3500
-
- dw ProfOakPic
- money 9900
-
- dw ChiefPic
- money 3000
-
- dw ScientistPic
- money 5000
-
- dw GiovanniPic
- money 9900
-
- dw RocketPic
- money 3000
-
- dw CooltrainerMPic
- money 3500
-
- dw CooltrainerFPic
- money 3500
-
- dw BrunoPic
- money 9900
-
- dw BrockPic
- money 9900
-
- dw MistyPic
- money 9900
-
- dw LtSurgePic
- money 9900
-
- dw ErikaPic
- money 9900
-
- dw KogaPic
- money 9900
-
- dw BlainePic
- money 9900
-
- dw SabrinaPic
- money 9900
-
- dw GentlemanPic
- money 7000
-
- dw Rival2Pic
- money 6500
-
- dw Rival3Pic
- money 9900
-
- dw LoreleiPic
- money 9900
-
- dw ChannelerPic
- money 3000
-
- dw AgathaPic
- money 9900
-
- dw LancePic
- money 9900
-
-INCLUDE "text/trainer_names.asm"
-
-; formats a string at wMovesString that lists the moves at wMoves
-FormatMovesString: ; 39b87 (e:5b87)
- ld hl, wMoves
- ld de, wMovesString
- ld b, $0
-.printMoveNameLoop
- ld a, [hli]
- and a ; end of move list?
- jr z, .printDashLoop ; print dashes when no moves are left
- push hl
- ld [wd0b5], a
- ld a, BANK(MoveNames)
- ld [wPredefBank], a
- ld a, MOVE_NAME
- ld [wNameListType], a
- call GetName
- ld hl, wcd6d
-.copyNameLoop
- ld a, [hli]
- cp $50
- jr z, .doneCopyingName
- ld [de], a
- inc de
- jr .copyNameLoop
-.doneCopyingName
- ld a, b
- ld [wcd6c], a
- inc b
- ld a, $4e ; line break
- ld [de], a
- inc de
- pop hl
- ld a, b
- cp NUM_MOVES
- jr z, .done
- jr .printMoveNameLoop
-.printDashLoop
- ld a, "-"
- ld [de], a
- inc de
- inc b
- ld a, b
- cp NUM_MOVES
- jr z, .done
- ld a, $4e ; line break
- ld [de], a
- inc de
- jr .printDashLoop
-.done
- ld a, "@"
- ld [de], a
- ret
-
-; XXX this is called in a few places, but it doesn't appear to do anything useful
-Func_39bd5: ; 39bd5 (e:5bd5)
- ld a, [wd11b]
- cp $1
- jr nz, .asm_39be6
- ld hl, wEnemyPartyCount
- ld de, wEnemyMonOT
- ld a, ENEMYOT_NAME
- jr .asm_39c18
-.asm_39be6
- cp $4
- jr nz, .calcAttackStat4
- ld hl, wPartyCount
- ld de, wPartyMonOT
- ld a, PLAYEROT_NAME
- jr .asm_39c18
-.calcAttackStat4
- cp $5
- jr nz, .asm_39c02
- ld hl, wStringBuffer2 + 11
- ld de, MonsterNames
- ld a, MONSTER_NAME
- jr .asm_39c18
-.asm_39c02
- cp $2
- jr nz, .asm_39c10
- ld hl, wNumBagItems
- ld de, ItemNames
- ld a, ITEM_NAME
- jr .asm_39c18
-.asm_39c10
- ld hl, wStringBuffer2 + 11
- ld de, ItemNames
- ld a, ITEM_NAME
-.asm_39c18
- ld [wNameListType], a
- ld a, l
- ld [wList], a
- ld a, h
- ld [wList + 1], a
- ld a, e
- ld [wcf8d], a
- ld a, d
- ld [wcf8e], a
- ld bc, ItemPrices
- ld a, c
- ld [wItemPrices], a
- ld a, b
- ld [wItemPrices + 1], a
- ret
-
-; get species of mon e in list [wcc49] for LoadMonData
-GetMonSpecies: ; 39c37 (e:5c37)
- ld hl, wPartySpecies
- ld a, [wcc49]
- and a
- jr z, .getSpecies
- dec a
- jr z, .enemyParty
- ld hl, wBoxSpecies
- jr .getSpecies
-.enemyParty
- ld hl, wEnemyPartyMons
-.getSpecies
- ld d, 0
- add hl, de
- ld a, [hl]
- ld [wcf91], a
- ret
-
-ReadTrainer: ; 39c53 (e:5c53)
-
-; don't change any moves in a link battle
- ld a,[wLinkState]
- and a
- ret nz
-
-; set [wEnemyPartyCount] to 0, [wEnemyPartyMons] to FF
-; XXX first is total enemy pokemon?
-; XXX second is species of first pokemon?
- ld hl,wEnemyPartyCount
- xor a
- ld [hli],a
- dec a
- ld [hl],a
-
-; get the pointer to trainer data for this class
- ld a,[W_CUROPPONENT]
- sub $C9 ; convert value from pokemon to trainer
- add a,a
- ld hl,TrainerDataPointers
- ld c,a
- ld b,0
- add hl,bc ; hl points to trainer class
- ld a,[hli]
- ld h,[hl]
- ld l,a
- ld a,[W_TRAINERNO]
- ld b,a
-; At this point b contains the trainer number,
-; and hl points to the trainer class.
-; Our next task is to iterate through the trainers,
-; decrementing b each time, until we get to the right one.
-.outer
- dec b
- jr z,.IterateTrainer
-.inner
- ld a,[hli]
- and a
- jr nz,.inner
- jr .outer
-
-; if the first byte of trainer data is FF,
-; - each pokemon has a specific level
-; (as opposed to the whole team being of the same level)
-; - if [W_LONEATTACKNO] != 0, one pokemon on the team has a special move
-; else the first byte is the level of every pokemon on the team
-.IterateTrainer
- ld a,[hli]
- cp $FF ; is the trainer special?
- jr z,.SpecialTrainer ; if so, check for special moves
- ld [W_CURENEMYLVL],a
-.LoopTrainerData
- ld a,[hli]
- and a ; have we reached the end of the trainer data?
- jr z,.FinishUp
- ld [wcf91],a ; write species somewhere (XXX why?)
- ld a,1
- ld [wcc49],a
- push hl
- call AddPartyMon
- pop hl
- jr .LoopTrainerData
-.SpecialTrainer
-; if this code is being run:
-; - each pokemon has a specific level
-; (as opposed to the whole team being of the same level)
-; - if [W_LONEATTACKNO] != 0, one pokemon on the team has a special move
- ld a,[hli]
- and a ; have we reached the end of the trainer data?
- jr z,.AddLoneMove
- ld [W_CURENEMYLVL],a
- ld a,[hli]
- ld [wcf91],a
- ld a,1
- ld [wcc49],a
- push hl
- call AddPartyMon
- pop hl
- jr .SpecialTrainer
-.AddLoneMove
-; does the trainer have a single monster with a different move
- ld a,[W_LONEATTACKNO] ; Brock is 01, Misty is 02, Erika is 04, etc
- and a
- jr z,.AddTeamMove
- dec a
- add a,a
- ld c,a
- ld b,0
- ld hl,LoneMoves
- add hl,bc
- ld a,[hli]
- ld d,[hl]
- ld hl,wEnemyMon1Moves + 2
- ld bc,wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld [hl],d
- jr .FinishUp
-.AddTeamMove
-; check if our trainer's team has special moves
-
-; get trainer class number
- ld a,[W_CUROPPONENT]
- sub $C8
- ld b,a
- ld hl,TeamMoves
-
-; iterate through entries in TeamMoves, checking each for our trainer class
-.IterateTeamMoves
- ld a,[hli]
- cp b
- jr z,.GiveTeamMoves ; is there a match?
- inc hl ; if not, go to the next entry
- inc a
- jr nz,.IterateTeamMoves
-
- ; no matches found. is this trainer champion rival?
- ld a,b
- cp SONY3
- jr z,.ChampionRival
- jr .FinishUp ; nope
-.GiveTeamMoves
- ld a,[hl]
- ld [wEnemyMon5Moves + 2],a
- jr .FinishUp
-.ChampionRival ; give moves to his team
-
-; pidgeot
- ld a,SKY_ATTACK
- ld [wEnemyMon1Moves + 2],a
-
-; starter
- ld a,[W_RIVALSTARTER]
- cp STARTER3
- ld b,MEGA_DRAIN
- jr z,.GiveStarterMove
- cp STARTER1
- ld b,FIRE_BLAST
- jr z,.GiveStarterMove
- ld b,BLIZZARD ; must be squirtle
-.GiveStarterMove
- ld a,b
- ld [wEnemyMon6Moves + 2],a
-.FinishUp ; XXX this needs documenting
- xor a ; clear D079-D07B
- ld de,wd079
- ld [de],a
- inc de
- ld [de],a
- inc de
- ld [de],a
- ld a,[W_CURENEMYLVL]
- ld b,a
-.LastLoop
- ld hl,wd047
- ld c,2
- push bc
- predef AddBCDPredef
- pop bc
- inc de
- inc de
- dec b
- jr nz,.LastLoop
- ret
-
-INCLUDE "data/trainer_moves.asm"
-
-INCLUDE "data/trainer_parties.asm"
-
-TrainerAI: ; 3a52e (e:652e)
-;XXX called at 34964, 3c342, 3c398
- and a
- ld a,[W_ISINBATTLE]
- dec a
- ret z ; if not a trainer, we're done here
- ld a,[wLinkState]
- cp LINK_STATE_BATTLING
- ret z
- ld a,[W_TRAINERCLASS] ; what trainer class is this?
- dec a
- ld c,a
- ld b,0
- ld hl,TrainerAIPointers
- add hl,bc
- add hl,bc
- add hl,bc
- ld a,[wAICount]
- and a
- ret z ; if no AI uses left, we're done here
- inc hl
- inc a
- jr nz,.getpointer
- dec hl
- ld a,[hli]
- ld [wAICount],a
-.getpointer
- ld a,[hli]
- ld h,[hl]
- ld l,a
- call Random
- jp [hl]
-
-TrainerAIPointers: ; 3a55c (e:655c)
-; one entry per trainer class
-; first byte, number of times (per Pokémon) it can occur
-; next two bytes, pointer to AI subroutine for trainer class
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,JugglerAI ; juggler_x
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 3,JugglerAI ; juggler
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 2,BlackbeltAI ; blackbelt
- dbw 3,GenericAI
- dbw 3,GenericAI
- dbw 1,GenericAI ; chief
- dbw 3,GenericAI
- dbw 1,GiovanniAI ; giovanni
- dbw 3,GenericAI
- dbw 2,CooltrainerMAI ; cooltrainerm
- dbw 1,CooltrainerFAI ; cooltrainerf
- dbw 2,BrunoAI ; bruno
- dbw 5,BrockAI ; brock
- dbw 1,MistyAI ; misty
- dbw 1,LtSurgeAI ; surge
- dbw 1,ErikaAI ; erika
- dbw 2,KogaAI ; koga
- dbw 2,BlaineAI ; blaine
- dbw 1,SabrinaAI ; sabrina
- dbw 3,GenericAI
- dbw 1,Sony2AI ; sony2
- dbw 1,Sony3AI ; sony3
- dbw 2,LoreleiAI ; lorelei
- dbw 3,GenericAI
- dbw 2,AgathaAI ; agatha
- dbw 1,LanceAI ; lance
-
-JugglerAI: ; 3a5e9 (e:65e9)
- cp $40
- ret nc
- jp AISwitchIfEnoughMons
-
-BlackbeltAI: ; 3a5ef (e:65ef)
- cp $20
- ret nc
- jp AIUseXAttack
-
-GiovanniAI: ; 3a5f5 (e:65f5)
- cp $40
- ret nc
- jp AIUseGuardSpec
-
-CooltrainerMAI: ; 3a5fb (e:65fb)
- cp $40
- ret nc
- jp AIUseXAttack
-
-CooltrainerFAI: ; 3a601 (e:6601)
- cp $40
- ld a,$A
- call AICheckIfHPBelowFraction
- jp c,AIUseHyperPotion
- ld a,5
- call AICheckIfHPBelowFraction
- ret nc
- jp AISwitchIfEnoughMons
-
-BrockAI: ; 3a614 (e:6614)
-; if his active monster has a status condition, use a full heal
- ld a,[wEnemyMonStatus]
- and a
- ret z
- jp AIUseFullHeal
-
-MistyAI: ; 3a61c (e:661c)
- cp $40
- ret nc
- jp AIUseXDefend
-
-LtSurgeAI: ; 3a622 (e:6622)
- cp $40
- ret nc
- jp AIUseXSpeed
-
-ErikaAI: ; 3a628 (e:6628)
- cp $80
- ret nc
- ld a,$A
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUseSuperPotion
-
-KogaAI: ; 3a634 (e:6634)
- cp $40
- ret nc
- jp AIUseXAttack
-
-BlaineAI: ; 3a63a (e:663a)
- cp $40
- ret nc
- jp AIUseSuperPotion
-
-SabrinaAI: ; 3a640 (e:6640)
- cp $40
- ret nc
- ld a,$A
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUseHyperPotion
-
-Sony2AI: ; 3a64c (e:664c)
- cp $20
- ret nc
- ld a,5
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUsePotion
-
-Sony3AI: ; 3a658 (e:6658)
- cp $20
- ret nc
- ld a,5
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUseFullRestore
-
-LoreleiAI: ; 3a664 (e:6664)
- cp $80
- ret nc
- ld a,5
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUseSuperPotion
-
-BrunoAI: ; 3a670 (e:6670)
- cp $40
- ret nc
- jp AIUseXDefend
-
-AgathaAI: ; 3a676 (e:6676)
- cp $14
- jp c,AISwitchIfEnoughMons
- cp $80
- ret nc
- ld a,4
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUseSuperPotion
-
-LanceAI: ; 3a687 (e:6687)
- cp $80
- ret nc
- ld a,5
- call AICheckIfHPBelowFraction
- ret nc
- jp AIUseHyperPotion
-
-GenericAI: ; 3a693 (e:6693)
- and a ; clear carry
- ret
-
-; end of individual trainer AI routines
-
-DecrementAICount: ; 3a695 (e:6695)
- ld hl,wAICount
- dec [hl]
- scf
- ret
-
-Func_3a69b: ; 3a69b (e:669b)
- ld a,(SFX_08_3e - SFX_Headers_08) / 3
- jp PlaySoundWaitForCurrent
-
-AIUseFullRestore: ; 3a6a0 (e:66a0)
- call AICureStatus
- ld a,FULL_RESTORE
- ld [wcf05],a
- ld de,wHPBarOldHP
- ld hl,wEnemyMonHP + 1
- ld a,[hld]
- ld [de],a
- inc de
- ld a,[hl]
- ld [de],a
- inc de
- ld hl,wEnemyMonMaxHP + 1
- ld a,[hld]
- ld [de],a
- inc de
- ld [wHPBarMaxHP],a
- ld [wEnemyMonHP + 1],a
- ld a,[hl]
- ld [de],a
- ld [wHPBarMaxHP+1],a
- ld [wEnemyMonHP],a
- jr AIPrintItemUseAndUpdateHPBar
-
-AIUsePotion: ; 3a6ca (e:66ca)
-; enemy trainer heals his monster with a potion
- ld a,POTION
- ld b,20
- jr AIRecoverHP
-
-AIUseSuperPotion: ; 3a6d0 (e:66d0)
-; enemy trainer heals his monster with a super potion
- ld a,SUPER_POTION
- ld b,50
- jr AIRecoverHP
-
-AIUseHyperPotion: ; 3a6d6 (e:66d6)
-; enemy trainer heals his monster with a hyper potion
- ld a,HYPER_POTION
- ld b,200
- ; fallthrough
-
-AIRecoverHP: ; 3a6da (e:66da)
-; heal b HP and print "trainer used $(a) on pokemon!"
- ld [wcf05],a
- ld hl,wEnemyMonHP + 1
- ld a,[hl]
- ld [wHPBarOldHP],a
- add b
- ld [hld],a
- ld [wHPBarNewHP],a
- ld a,[hl]
- ld [wHPBarOldHP+1],a
- ld [wHPBarNewHP+1],a
- jr nc,.next
- inc a
- ld [hl],a
- ld [wHPBarNewHP+1],a
-.next
- inc hl
- ld a,[hld]
- ld b,a
- ld de,wEnemyMonMaxHP + 1
- ld a,[de]
- dec de
- ld [wHPBarMaxHP],a
- sub b
- ld a,[hli]
- ld b,a
- ld a,[de]
- ld [wHPBarMaxHP+1],a
- sbc b
- jr nc,AIPrintItemUseAndUpdateHPBar
- inc de
- ld a,[de]
- dec de
- ld [hld],a
- ld [wHPBarNewHP],a
- ld a,[de]
- ld [hl],a
- ld [wHPBarNewHP+1],a
- ; fallthrough
-
-AIPrintItemUseAndUpdateHPBar: ; 3a718 (e:6718)
- call AIPrintItemUse_
- hlCoord 2, 2
- xor a
- ld [wHPBarType],a
- predef UpdateHPBar2
- jp DecrementAICount
-
-AISwitchIfEnoughMons: ; 3a72a (e:672a)
-; enemy trainer switches if there are 3 or more unfainted mons in party
- ld a,[wEnemyPartyCount]
- ld c,a
- ld hl,wEnemyMon1HP
-
- ld d,0 ; keep count of unfainted monsters
-
- ; count how many monsters haven't fainted yet
-.loop
- ld a,[hli]
- ld b,a
- ld a,[hld]
- or b
- jr z,.Fainted ; has monster fainted?
- inc d
-.Fainted
- push bc
- ld bc,$2C
- add hl,bc
- pop bc
- dec c
- jr nz,.loop
-
- ld a,d ; how many available monsters are there?
- cp 2 ; don't bother if only 1 or 2
- jp nc,SwitchEnemyMon
- and a
- ret
-
-SwitchEnemyMon: ; 3a74b (e:674b)
-
-; prepare to withdraw the active monster: copy hp, number, and status to roster
-
- ld a,[wEnemyMonPartyPos]
- ld hl,wEnemyMon1HP
- ld bc,wEnemyMon2 - wEnemyMon1
- call AddNTimes
- ld d,h
- ld e,l
- ld hl,wEnemyMonHP
- ld bc,4
- call CopyData
-
- ld hl, AIBattleWithdrawText
- call PrintText
-
- ld a,1
- ld [wd11d],a
- callab EnemySendOut
- xor a
- ld [wd11d],a
-
- ld a,[wLinkState]
- cp LINK_STATE_BATTLING
- ret z
- scf
- ret
-
-AIBattleWithdrawText: ; 3a781 (e:6781)
- TX_FAR _AIBattleWithdrawText
- db "@"
-
-AIUseFullHeal: ; 3a786 (e:6786)
- call Func_3a69b
- call AICureStatus
- ld a,FULL_HEAL
- jp AIPrintItemUse
-
-AICureStatus: ; 3a791 (e:6791)
-; cures the status of enemy's active pokemon
- ld a,[wEnemyMonPartyPos]
- ld hl,wEnemyMon1Status
- ld bc,wEnemyMon2 - wEnemyMon1
- call AddNTimes
- xor a
- ld [hl],a ; clear status in enemy team roster
- ld [wEnemyMonStatus],a ; clear status of active enemy
- ld hl,W_ENEMYBATTSTATUS3
- res 0,[hl]
- ret
-
-AIUseXAccuracy: ; 0x3a7a8 unused
- call Func_3a69b
- ld hl,W_ENEMYBATTSTATUS2
- set 0,[hl]
- ld a,X_ACCURACY
- jp AIPrintItemUse
-
-AIUseGuardSpec: ; 3a7b5 (e:67b5)
- call Func_3a69b
- ld hl,W_ENEMYBATTSTATUS2
- set 1,[hl]
- ld a,GUARD_SPEC_
- jp AIPrintItemUse
-
-AIUseDireHit: ; 0x3a7c2 unused
- call Func_3a69b
- ld hl,W_ENEMYBATTSTATUS2
- set 2,[hl]
- ld a,DIRE_HIT
- jp AIPrintItemUse
-
-AICheckIfHPBelowFraction: ; 3a7cf (e:67cf)
-; return carry if enemy trainer's current HP is below 1 / a of the maximum
- ld [H_DIVISOR],a
- ld hl,wEnemyMonMaxHP
- ld a,[hli]
- ld [H_DIVIDEND],a
- ld a,[hl]
- ld [H_DIVIDEND + 1],a
- ld b,2
- call Divide
- ld a,[H_QUOTIENT + 3]
- ld c,a
- ld a,[H_QUOTIENT + 2]
- ld b,a
- ld hl,wEnemyMonHP + 1
- ld a,[hld]
- ld e,a
- ld a,[hl]
- ld d,a
- ld a,d
- sub b
- ret nz
- ld a,e
- sub c
- ret
-
-AIUseXAttack: ; 3a7f2 (e:67f2)
- ld b,$A
- ld a,X_ATTACK
- jr AIIncreaseStat
-
-AIUseXDefend: ; 3a7f8 (e:67f8)
- ld b,$B
- ld a,X_DEFEND
- jr AIIncreaseStat
-
-AIUseXSpeed: ; 3a7fe (e:67fe)
- ld b,$C
- ld a,X_SPEED
- jr AIIncreaseStat
-
-AIUseXSpecial: ; 3a804 (e:6804)
- ld b,$D
- ld a,X_SPECIAL
- ; fallthrough
-
-AIIncreaseStat: ; 3a808 (e:6808)
- ld [wcf05],a
- push bc
- call AIPrintItemUse_
- pop bc
- ld hl,W_ENEMYMOVEEFFECT
- ld a,[hld]
- push af
- ld a,[hl]
- push af
- push hl
- ld a,$AF
- ld [hli],a
- ld [hl],b
- callab StatModifierUpEffect
- pop hl
- pop af
- ld [hli],a
- pop af
- ld [hl],a
- jp DecrementAICount
-
-AIPrintItemUse: ; 3a82c (e:682c)
- ld [wcf05],a
- call AIPrintItemUse_
- jp DecrementAICount
-
-AIPrintItemUse_: ; 3a835 (e:6835)
-; print "x used [wcf05] on z!"
- ld a,[wcf05]
- ld [wd11e],a
- call GetItemName
- ld hl, AIBattleUseItemText
- jp PrintText
-
-AIBattleUseItemText: ; 3a844 (e:6844)
- TX_FAR _AIBattleUseItemText
- db "@"
-
-DrawAllPokeballs: ; 3a849 (e:6849)
- call LoadPartyPokeballGfx
- call SetupOwnPartyPokeballs
- ld a, [W_ISINBATTLE] ; W_ISINBATTLE
- dec a
- ret z ; return if wild pokémon
- jp SetupEnemyPartyPokeballs
-
-DrawEnemyPokeballs: ; 0x3a857
- call LoadPartyPokeballGfx
- jp SetupEnemyPartyPokeballs
-
-LoadPartyPokeballGfx: ; 3a85d (e:685d)
- ld de, PokeballTileGraphics ; $697e
- ld hl, vSprites + $310
- ld bc, (BANK(PokeballTileGraphics) << 8) + $04
- jp CopyVideoData
-
-SetupOwnPartyPokeballs: ; 3a869 (e:6869)
- call PlacePlayerHUDTiles
- ld hl, wPartyMon1
- ld de, wPartyCount ; wPartyCount
- call SetupPokeballs
- ld a, $60
- ld hl, W_BASECOORDX ; wd081
- ld [hli], a
- ld [hl], a
- ld a, $8
- ld [wTrainerEngageDistance], a
- ld hl, wOAMBuffer
- jp WritePokeballOAMData
-
-SetupEnemyPartyPokeballs: ; 3a887 (e:6887)
- call PlaceEnemyHUDTiles
- ld hl, wEnemyMons
- ld de, wEnemyPartyCount ; wEnemyPartyCount
- call SetupPokeballs
- ld hl, W_BASECOORDX ; wd081
- ld a, $48
- ld [hli], a
- ld [hl], $20
- ld a, $f8
- ld [wTrainerEngageDistance], a
- ld hl, wOAMBuffer + PARTY_LENGTH * 4
- jp WritePokeballOAMData
-
-SetupPokeballs: ; 0x3a8a6
- ld a, [de]
- push af
- ld de, wBuffer
- ld c, PARTY_LENGTH
- ld a, $34 ; empty pokeball
-.emptyloop
- ld [de], a
- inc de
- dec c
- jr nz, .emptyloop
- pop af
- ld de, wBuffer
-.monloop
- push af
- call PickPokeball
- inc de
- pop af
- dec a
- jr nz, .monloop
- ret
-
-PickPokeball: ; 3a8c2 (e:68c2)
- inc hl
- ld a, [hli]
- and a
- jr nz, .alive
- ld a, [hl]
- and a
- ld b, $33 ; crossed ball (fainted)
- jr z, .done_fainted
-.alive
- inc hl
- inc hl
- ld a, [hl] ; status
- and a
- ld b, $32 ; black ball (status)
- jr nz, .done
- dec b ; regular ball
- jr .done
-.done_fainted
- inc hl
- inc hl
-.done
- ld a, b
- ld [de], a
- ld bc, $0028 ; rest of mon struct
- add hl, bc
- ret
-
-WritePokeballOAMData: ; 3a8e1 (e:68e1)
- ld de, wBuffer
- ld c, PARTY_LENGTH
-.loop
- ld a, [W_BASECOORDY] ; wd082
- ld [hli], a
- ld a, [W_BASECOORDX] ; wd081
- ld [hli], a
- ld a, [de]
- ld [hli], a
- xor a
- ld [hli], a
- ld a, [W_BASECOORDX] ; wd081
- ld b, a
- ld a, [wTrainerEngageDistance]
- add b
- ld [W_BASECOORDX], a ; wd081
- inc de
- dec c
- jr nz, .loop
- ret
-
-PlacePlayerHUDTiles: ; 3a902 (e:6902)
- ld hl, PlayerBattleHUDGraphicsTiles ; $6916
- ld de, wTrainerFacingDirection
- ld bc, $3
- call CopyData
- hlCoord 18, 10
- ld de, rIE ; $ffff
- jr PlaceHUDTiles
-
-PlayerBattleHUDGraphicsTiles: ; 3a916 (e:6916)
-; The tile numbers for specific parts of the battle display for the player's pokemon
- db $73 ; unused ($73 is hardcoded into the routine that uses these bytes)
- db $77 ; lower-right corner tile of the HUD
- db $6F ; lower-left triangle tile of the HUD
-
-PlaceEnemyHUDTiles: ; 3a919 (e:6919)
- ld hl, EnemyBattleHUDGraphicsTiles ; $692d
- ld de, wTrainerFacingDirection
- ld bc, $3
- call CopyData
- hlCoord 1, 2
- ld de, $1
- jr PlaceHUDTiles
-
-EnemyBattleHUDGraphicsTiles: ; 3a92d (e:692d)
-; The tile numbers for specific parts of the battle display for the enemy
- db $73 ; unused ($73 is hardcoded in the routine that uses these bytes)
- db $74 ; lower-left corner tile of the HUD
- db $78 ; lower-right triangle tile of the HUD
-
-PlaceHUDTiles: ; 3a930 (e:6930)
- ld [hl], $73
- ld bc, $14
- add hl, bc
- ld a, [wTrainerScreenY]
- ld [hl], a
- ld a, $8
-.asm_3a93c
- add hl, de
- ld [hl], $76
- dec a
- jr nz, .asm_3a93c
- add hl, de
- ld a, [wTrainerScreenX]
- ld [hl], a
- ret
-
-SetupPlayerAndEnemyPokeballs: ; 3a948 (e:6948)
- call LoadPartyPokeballGfx
- ld hl, wPartyMon1Species ; wPartyMon1Species (aliases: wPartyMon1)
- ld de, wPartyCount ; wPartyCount
- call SetupPokeballs
- ld hl, W_BASECOORDX ; wd081
- ld a, $50
- ld [hli], a
- ld [hl], $40
- ld a, $8
- ld [wTrainerEngageDistance], a
- ld hl, wOAMBuffer
- call WritePokeballOAMData
- ld hl, wEnemyMons ; wEnemyMon1Species
- ld de, wEnemyPartyCount ; wEnemyPartyCount
- call SetupPokeballs
- ld hl, W_BASECOORDX ; wd081
- ld a, $50
- ld [hli], a
- ld [hl], $68
- ld hl, wOAMBuffer + $18
- jp WritePokeballOAMData
-
-; four tiles: pokeball, black pokeball (status ailment), crossed out pokeball (faited) and pokeball slot (no mon)
-PokeballTileGraphics:: ; 3a97e (e:697e)
- INCBIN "gfx/pokeball.2bpp"
--- a/engine/battle/e_2.asm
+++ /dev/null
@@ -1,301 +1,0 @@
-HealEffect_: ; 3b9ec (e:79ec)
- ld a, [H_WHOSETURN]
- and a
- ld de, wBattleMonHP
- ld hl, wBattleMonMaxHP
- ld a, [W_PLAYERMOVENUM]
- jr z, .asm_3ba03
- ld de, wEnemyMonHP
- ld hl, wEnemyMonMaxHP
- ld a, [W_ENEMYMOVENUM]
-.asm_3ba03
- ld b, a
- ld a, [de]
- cp [hl]
- inc de
- inc hl
- ld a, [de]
- sbc [hl]
- jp z, .failed
- ld a, b
- cp REST
- jr nz, .asm_3ba37
- push hl
- push de
- push af
- ld c, 50
- call DelayFrames
- ld hl, wBattleMonStatus
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_3ba25
- ld hl, wEnemyMonStatus
-.asm_3ba25
- ld a, [hl]
- and a
- ld [hl], 2 ; Number of turns from Rest
- ld hl, StartedSleepingEffect
- jr z, .asm_3ba31
- ld hl, FellAsleepBecameHealthyText
-.asm_3ba31
- call PrintText
- pop af
- pop de
- pop hl
-.asm_3ba37
- ld a, [hld]
- ld [wHPBarMaxHP], a
- ld c, a
- ld a, [hl]
- ld [wHPBarMaxHP+1], a
- ld b, a
- jr z, .asm_3ba47
- srl b
- rr c
-.asm_3ba47
- ld a, [de]
- ld [wHPBarOldHP], a
- add c
- ld [de], a
- ld [wHPBarNewHP], a
- dec de
- ld a, [de]
- ld [wHPBarOldHP+1], a
- adc b
- ld [de], a
- ld [wHPBarNewHP+1], a
- inc hl
- inc de
- ld a, [de]
- dec de
- sub [hl]
- dec hl
- ld a, [de]
- sbc [hl]
- jr c, .asm_3ba6f
- ld a, [hli]
- ld [de], a
- ld [wHPBarNewHP+1], a
- inc de
- ld a, [hl]
- ld [de], a
- ld [wHPBarNewHP], a
-.asm_3ba6f
- ld hl, PlayCurrentMoveAnimation
- call BankswitchEtoF
- ld a, [H_WHOSETURN]
- and a
- hlCoord 10, 9
- ld a, $1
- jr z, .asm_3ba83
- hlCoord 2, 2
- xor a
-.asm_3ba83
- ld [wHPBarType], a
- predef UpdateHPBar2
- ld hl, DrawHUDsAndHPBars
- call BankswitchEtoF
- ld hl, RegainedHealthText
- jp PrintText
-.failed
- ld c, 50
- call DelayFrames
- ld hl, PrintButItFailedText_
- jp BankswitchEtoF
-
-StartedSleepingEffect: ; 3baa2 (e:7aa2)
- TX_FAR _StartedSleepingEffect
- db "@"
-
-FellAsleepBecameHealthyText: ; 3baa7 (e:7aa7)
- TX_FAR _FellAsleepBecameHealthyText
- db "@"
-
-RegainedHealthText: ; 3baac (e:7aac)
- TX_FAR _RegainedHealthText
- db "@"
-
-TransformEffect_: ; 3bab1 (e:7ab1)
- ld hl, wBattleMonSpecies
- ld de, wEnemyMonSpecies
- ld bc, W_ENEMYBATTSTATUS3
- ld a, [W_ENEMYBATTSTATUS1]
- ld a, [H_WHOSETURN]
- and a
- jr nz, .asm_3bad1
- ld hl, wEnemyMonSpecies
- ld de, wBattleMonSpecies
- ld bc, W_PLAYERBATTSTATUS3
- ld [wPlayerMoveListIndex], a
- ld a, [W_PLAYERBATTSTATUS1]
-.asm_3bad1
- bit Invulnerable, a ; is mon invulnerable to typical attacks? (fly/dig)
- jp nz, .failed
- push hl
- push de
- push bc
- ld hl, W_PLAYERBATTSTATUS2
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_3bae4
- ld hl, W_ENEMYBATTSTATUS2
-.asm_3bae4
- bit HasSubstituteUp, [hl]
- push af
- ld hl, Func_79747
- ld b, BANK(Func_79747)
- call nz, Bankswitch
- ld a, [W_OPTIONS]
- add a
- ld hl, PlayCurrentMoveAnimation
- ld b, BANK(PlayCurrentMoveAnimation)
- jr nc, .asm_3baff
- ld hl, AnimationTransformMon
- ld b, BANK(AnimationTransformMon)
-.asm_3baff
- call Bankswitch
- ld hl, Func_79771
- ld b, BANK(Func_79771)
- pop af
- call nz, Bankswitch
- pop bc
- ld a, [bc]
- set Transformed, a
- ld [bc], a
- pop de
- pop hl
- push hl
- ld a, [hl]
- ld [de], a
- ld bc, $5
- add hl, bc
- inc de
- inc de
- inc de
- inc de
- inc de
- inc bc
- inc bc
- call CopyData
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_3bb32
- ld a, [de]
- ld [wcceb], a
- inc de
- ld a, [de]
- ld [wccec], a
- dec de
-.asm_3bb32
- ld a, [hli]
- ld [de], a
- inc de
- ld a, [hli]
- ld [de], a
- inc de
- inc hl
- inc hl
- inc hl
- inc de
- inc de
- inc de
- ld bc, $8
- call CopyData
- ld bc, $ffef
- add hl, bc
- ld b, $4
-.asm_3bb4a
- ld a, [hli]
- and a
- jr z, .asm_3bb57
- ld a, $5
- ld [de], a
- inc de
- dec b
- jr nz, .asm_3bb4a
- jr .asm_3bb5d
-.asm_3bb57
- xor a
- ld [de], a
- inc de
- dec b
- jr nz, .asm_3bb57
-.asm_3bb5d
- pop hl
- ld a, [hl]
- ld [wd11e], a
- call GetMonName
- ld hl, wEnemyMonUnmodifiedAttack
- ld de, wPlayerMonUnmodifiedAttack
- call .copyBasedOnTurn
- ld hl, wEnemyMonStatMods
- ld de, wPlayerMonStatMods
- call .copyBasedOnTurn
- ld hl, TransformedText
- jp PrintText
-
-.copyBasedOnTurn
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_3bb86
- push hl
- ld h, d
- ld l, e
- pop de
-.asm_3bb86
- ld bc, $8
- jp CopyData
-
-.failed
- ld hl, PrintButItFailedText_
- jp BankswitchEtoF
-
-TransformedText: ; 3bb92 (e:7b92)
- TX_FAR _TransformedText
- db "@"
-
-ReflectLightScreenEffect_: ; 3bb97 (e:7b97)
- ld hl, W_PLAYERBATTSTATUS3
- ld de, W_PLAYERMOVEEFFECT
- ld a, [H_WHOSETURN]
- and a
- jr z, .asm_3bba8
- ld hl, W_ENEMYBATTSTATUS3
- ld de, W_ENEMYMOVEEFFECT
-.asm_3bba8
- ld a, [de]
- cp LIGHT_SCREEN_EFFECT
- jr nz, .reflect
- bit HasLightScreenUp, [hl] ; is mon already protected by light screen?
- jr nz, .moveFailed
- set HasLightScreenUp, [hl] ; mon is now protected by light screen
- ld hl, LightScreenProtectedText
- jr .asm_3bbc1
-.reflect
- bit HasReflectUp, [hl] ; is mon already protected by reflect?
- jr nz, .moveFailed
- set HasReflectUp, [hl] ; mon is now protected by reflect
- ld hl, ReflectGainedArmorText
-.asm_3bbc1
- push hl
- ld hl, PlayCurrentMoveAnimation
- call BankswitchEtoF
- pop hl
- jp PrintText
-.moveFailed
- ld c, $32
- call DelayFrames
- ld hl, PrintButItFailedText_
- jp BankswitchEtoF
-
-LightScreenProtectedText: ; 3bbd7 (e:7bd7)
- TX_FAR _LightScreenProtectedText
- db "@"
-
-ReflectGainedArmorText: ; 3bbdc (e:7bdc)
- TX_FAR _ReflectGainedArmorText
- db "@"
-
-BankswitchEtoF: ; 3bbe1 (e:7be1)
- ld b, BANK(BattleCore)
- jp Bankswitch
--- /dev/null
+++ b/engine/battle/end_of_battle.asm
@@ -1,0 +1,88 @@
+EndOfBattle: ; 137aa (4:77aa)
+ ld a, [wLinkState]
+ cp LINK_STATE_BATTLING
+ jr nz, .notLinkBattle
+; link battle
+ ld a, [wEnemyMonPartyPos]
+ ld hl, wEnemyMon1Status
+ ld bc, wEnemyMon2 - wEnemyMon1
+ call AddNTimes
+ ld a, [wEnemyMonStatus]
+ ld [hl], a
+ call ClearScreen
+ callab DisplayLinkBattleVersusTextBox
+ ld a, [wBattleResult]
+ cp $1
+ ld de, YouWinText
+ jr c, .placeWinOrLoseString
+ ld de, YouLoseText
+ jr z, .placeWinOrLoseString
+ ld de, DrawText
+.placeWinOrLoseString
+ hlCoord 6, 8
+ call PlaceString
+ ld c, $c8
+ call DelayFrames
+ jr .evolution
+.notLinkBattle
+ ld a, [wBattleResult]
+ and a
+ jr nz, .resetVariables
+ ld hl, wTotalPayDayMoney
+ ld a, [hli]
+ or [hl]
+ inc hl
+ or [hl]
+ jr z, .evolution ; if pay day money is 0, jump
+ ld de, wPlayerMoney + 2
+ ld c, $3
+ predef AddBCDPredef
+ ld hl, PickUpPayDayMoneyText
+ call PrintText
+.evolution
+ xor a
+ ld [wccd4], a
+ predef EvolutionAfterBattle
+.resetVariables
+ xor a
+ ld [wLowHealthAlarm], a ;disable low health alarm
+ ld [wc02a], a
+ ld [W_ISINBATTLE], a
+ ld [W_BATTLETYPE], a
+ ld [W_MOVEMISSED], a
+ ld [W_CUROPPONENT], a
+ ld [wd11f], a
+ ld [wNumRunAttempts], a
+ ld [wEscapedFromBattle], a
+ ld hl, wcc2b
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld [wListScrollOffset], a
+ ld hl, wPlayerStatsToDouble
+ ld b, $18
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ ld hl, wd72c
+ set 0, [hl]
+ call WaitForSoundToFinish
+ call GBPalWhiteOut
+ ld a, $ff
+ ld [wDestinationWarpID], a
+ ret
+
+YouWinText: ; 13853 (4:7853)
+ db "YOU WIN@"
+
+YouLoseText: ; 1385b (4:785b)
+ db "YOU LOSE@"
+
+DrawText: ; 13864 (4:7864)
+ db " DRAW@"
+
+PickUpPayDayMoneyText: ; 1386b (4:786b)
+ TX_FAR _PickUpPayDayMoneyText
+ db "@"
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/experience.asm
@@ -1,0 +1,372 @@
+GainExperience: ; 5524f (15:524f)
+ ld a, [wLinkState]
+ cp LINK_STATE_BATTLING
+ ret z ; return if link battle
+ call DivideExpDataByNumMonsGainingExp
+ ld hl, wPartyMon1
+ xor a
+ ld [wWhichPokemon], a
+.partyMonLoop ; loop over each mon and add gained exp
+ inc hl
+ ld a, [hli]
+ or [hl] ; is mon's HP 0?
+ jp z, .nextMon ; if so, go to next mon
+ push hl
+ ld hl, wPartyGainExpFlags
+ ld a, [wWhichPokemon]
+ ld c, a
+ ld b, $2
+ predef FlagActionPredef
+ ld a, c
+ and a ; is mon's gain exp flag set?
+ pop hl
+ jp z, .nextMon ; if mon's gain exp flag not set, go to next mon
+ ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1)
+ add hl, de
+ ld d, h
+ ld e, l
+ ld hl, wEnemyMonBaseStats
+ ld c, $5
+.gainStatExpLoop
+ ld a, [hli]
+ ld b, a ; enemy mon base stat
+ ld a, [de] ; stat exp
+ add b ; add enemy mon base state to stat exp
+ ld [de], a
+ jr nc, .nextBaseStat
+; if there was a carry, increment the upper byte
+ dec de
+ ld a, [de]
+ inc a
+ jr z, .maxStatExp ; jump if the value overflowed
+ ld [de], a
+ inc de
+ jr .nextBaseStat
+.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp
+ ld a, $ff
+ ld [de], a
+ inc de
+ ld [de], a
+.nextBaseStat
+ dec c
+ jr z, .asm_552a1
+ inc de
+ inc de
+ jr .gainStatExpLoop
+.asm_552a1
+ xor a
+ ld [H_MULTIPLICAND], a
+ ld [H_MULTIPLICAND + 1], a
+ ld a, [wEnemyMonBaseExp]
+ ld [H_MULTIPLICAND + 2], a
+ ld a, [wEnemyMonLevel]
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld a, 7
+ ld [H_DIVISOR], a
+ ld b, 4
+ call Divide
+ ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2)
+ add hl, de
+ ld b, [hl] ; party mon OTID
+ inc hl
+ ld a, [wPlayerID]
+ cp b
+ jr nz, .tradedMon
+ ld b, [hl]
+ ld a, [wPlayerID + 1]
+ cp b
+ ld a, $0
+ jr z, .next
+.tradedMon
+ call BoostExp ; traded mon exp boost
+ ld a, $1
+.next
+ ld [wGainBoostedExp], a
+ ld a, [W_ISINBATTLE]
+ dec a ; is it a trainer battle?
+ call nz, BoostExp ; if so, boost exp
+ inc hl
+ inc hl
+ inc hl
+; add the gained exp to the party mon's exp
+ ld b, [hl]
+ ld a, [H_QUOTIENT + 3]
+ ld [wcf4c], a
+ add b
+ ld [hld], a
+ ld b, [hl]
+ ld a, [H_QUOTIENT + 2]
+ ld [wcf4b], a
+ adc b
+ ld [hl], a
+ jr nc, .noCarry
+ dec hl
+ inc [hl]
+ inc hl
+.noCarry
+; calculate exp for the mon at max level, and cap the exp at that value
+ inc hl
+ push hl
+ ld a, [wWhichPokemon]
+ ld c, a
+ ld b, 0
+ ld hl, wPartySpecies
+ add hl, bc
+ ld a, [hl] ; species
+ ld [wd0b5], a
+ call GetMonHeader
+ ld d, MAX_LEVEL
+ callab CalcExperience ; get max exp
+; compare max exp with current exp
+ ld a, [$ff96]
+ ld b, a
+ ld a, [$ff97]
+ ld c, a
+ ld a, [$ff98]
+ ld d, a
+ pop hl
+ ld a, [hld]
+ sub d
+ ld a, [hld]
+ sbc c
+ ld a, [hl]
+ sbc b
+ jr c, .next2
+; the mon's exp is greater than the max exp, so overwrite it with the max exp
+ ld a, b
+ ld [hli], a
+ ld a, c
+ ld [hli], a
+ ld a, d
+ ld [hld], a
+ dec hl
+.next2
+ push hl
+ ld a, [wWhichPokemon]
+ ld hl, wPartyMonNicks
+ call GetPartyMonName
+ ld hl, GainedText
+ call PrintText
+ xor a ; party mon data
+ ld [wcc49], a
+ call LoadMonData
+ pop hl
+ ld bc, wPartyMon1Level - wPartyMon1Exp
+ add hl, bc
+ push hl
+ callba CalcLevelFromExperience
+ pop hl
+ ld a, [hl] ; current level
+ cp d
+ jp z, .nextMon ; if level didn't change, go to next mon
+ ld a, [W_CURENEMYLVL]
+ push af
+ push hl
+ ld a, d
+ ld [W_CURENEMYLVL], a
+ ld [hl], a
+ ld bc, wPartyMon1Species - wPartyMon1Level
+ add hl, bc
+ ld a, [hl] ; species
+ ld [wd0b5], a
+ ld [wd11e], a
+ call GetMonHeader
+ ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species
+ add hl, bc
+ push hl
+ ld a, [hld]
+ ld c, a
+ ld b, [hl]
+ push bc ; push max HP (from before levelling up)
+ ld d, h
+ ld e, l
+ ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP
+ add hl, bc
+ ld b, $1 ; consider stat exp when calculating stats
+ call CalcStats
+ pop bc ; pop max HP (from before levelling up)
+ pop hl
+ ld a, [hld]
+ sub c
+ ld c, a
+ ld a, [hl]
+ sbc b
+ ld b, a ; bc = difference between old max HP and new max HP after levelling
+ ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
+ add hl, de
+; add to the current HP the amount of max HP gained when levelling
+ ld a, [hl] ; wPartyMon1HP + 1
+ add c
+ ld [hld], a
+ ld a, [hl] ; wPartyMon1HP + 1
+ adc b
+ ld [hl], a ; wPartyMon1HP
+ ld a, [wPlayerMonNumber]
+ ld b, a
+ ld a, [wWhichPokemon]
+ cp b ; is the current mon in battle?
+ jr nz, .printGrewLevelText
+; current mon is in battle
+ ld de, wBattleMonHP
+; copy party mon HP to battle mon HP
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+; copy other stats from party mon to battle mon
+ ld bc, wPartyMon1Level - (wPartyMon1HP + 1)
+ add hl, bc
+ push hl
+ ld de, wBattleMonLevel
+ ld bc, $b ; size of stats
+ call CopyData
+ pop hl
+ ld a, [W_PLAYERBATTSTATUS3]
+ bit 3, a ; is the mon transformed?
+ jr nz, .recalcStatChanges
+; the mon is not transformed, so update the unmodified stats
+ ld de, wPlayerMonUnmodifiedLevel
+ ld bc, $b
+ call CopyData
+.recalcStatChanges
+ xor a
+ ld [wd11e], a
+ callab CalculateModifiedStats
+ callab ApplyBurnAndParalysisPenaltiesToPlayer
+ callab ApplyBadgeStatBoosts
+ callab DrawPlayerHUDAndHPBar
+ callab PrintEmptyString
+ call SaveScreenTilesToBuffer1
+.printGrewLevelText
+ ld hl, GrewLevelText
+ call PrintText
+ xor a ; party mon data
+ ld [wcc49], a
+ call LoadMonData
+ ld d, $1
+ callab PrintStatsBox
+ call WaitForTextScrollButtonPress
+ call LoadScreenTilesFromBuffer1
+ xor a
+ ld [wcc49], a
+ ld a, [wd0b5]
+ ld [wd11e], a
+ predef LearnMoveFromLevelUp
+ ld hl, wccd3
+ ld a, [wWhichPokemon]
+ ld c, a
+ ld b, $1
+ predef FlagActionPredef
+ pop hl
+ pop af
+ ld [W_CURENEMYLVL], a
+
+.nextMon
+ ld a, [wPartyCount]
+ ld b, a
+ ld a, [wWhichPokemon]
+ inc a
+ cp b
+ jr z, .done
+ ld [wWhichPokemon], a
+ ld bc, wPartyMon2 - wPartyMon1
+ ld hl, wPartyMon1
+ call AddNTimes
+ jp .partyMonLoop
+.done
+ ld hl, wPartyGainExpFlags
+ xor a
+ ld [hl], a ; clear gain exp flags
+ ld a, [wPlayerMonNumber]
+ ld c, a
+ ld b, $1
+ push bc
+ predef FlagActionPredef ; set the gain exp flag for the mon that is currently out
+ ld hl, wPartyFoughtCurrentEnemyFlags
+ xor a
+ ld [hl], a
+ pop bc
+ predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out
+
+; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp
+DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c)
+ ld a, [wPartyGainExpFlags]
+ ld b, a
+ xor a
+ ld c, $8
+ ld d, $0
+.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags
+ xor a
+ srl b
+ adc d
+ ld d, a
+ dec c
+ jr nz, .countSetBitsLoop
+ cp $2
+ ret c ; return if only one mon is gaining exp
+ ld [wd11e], a ; store number of mons gaining exp
+ ld hl, wEnemyMonBaseStats
+ ld c, $7
+.divideLoop
+ xor a
+ ld [H_DIVIDEND], a
+ ld a, [hl]
+ ld [H_DIVIDEND + 1], a
+ ld a, [wd11e]
+ ld [H_DIVISOR], a
+ ld b, $2
+ call Divide ; divide value by number of mons gaining exp
+ ld a, [H_QUOTIENT + 3]
+ ld [hli], a
+ dec c
+ jr nz, .divideLoop
+ ret
+
+; multiplies exp by 1.5
+BoostExp: ; 5549f (15:549f)
+ ld a, [H_QUOTIENT + 2]
+ ld b, a
+ ld a, [H_QUOTIENT + 3]
+ ld c, a
+ srl b
+ rr c
+ add c
+ ld [H_QUOTIENT + 3], a
+ ld a, [H_QUOTIENT + 2]
+ adc b
+ ld [H_QUOTIENT + 2], a
+ ret
+
+GainedText: ; 554b2 (15:54b2)
+ TX_FAR _GainedText
+ db $08 ; asm
+ ld a, [wBoostExpByExpAll]
+ ld hl, WithExpAllText
+ and a
+ ret nz
+ ld hl, ExpPointsText
+ ld a, [wGainBoostedExp]
+ and a
+ ret z
+ ld hl, BoostedText
+ ret
+
+WithExpAllText: ; 554cb (15:54cb)
+ TX_FAR _WithExpAllText
+ db $08 ; asm
+ ld hl, ExpPointsText
+ ret
+
+BoostedText: ; 554d4 (15:54d4)
+ TX_FAR _BoostedText
+
+ExpPointsText: ; 554d8 (15:54d8)
+ TX_FAR _ExpPointsText
+ db "@"
+
+GrewLevelText: ; 554dd (15:54dd)
+ TX_FAR _GrewLevelText
+ db $0b
+ db "@"
--- /dev/null
+++ b/engine/battle/get_trainer_name.asm
@@ -1,0 +1,24 @@
+GetTrainerName_: ; 13a58 (4:7a58)
+ ld hl, W_GRASSRATE
+ ld a, [wLinkState]
+ and a
+ jr nz, .rival
+ ld hl, W_RIVALNAME
+ ld a, [W_TRAINERCLASS]
+ cp SONY1
+ jr z, .rival
+ cp SONY2
+ jr z, .rival
+ cp SONY3
+ jr z, .rival
+ ld [wd0b5], a
+ ld a, TRAINER_NAME
+ ld [wNameListType], a
+ ld a, BANK(TrainerNames)
+ ld [wPredefBank], a
+ call GetName
+ ld hl, wcd6d
+.rival
+ ld de, W_TRAINERNAME
+ ld bc, $d
+ jp CopyData
--- /dev/null
+++ b/engine/battle/ghost_marowak_anim.asm
@@ -1,0 +1,89 @@
+MarowakAnim: ; 708ca (1c:48ca)
+; animate the ghost being unveiled as a Marowak
+ ld a, $e4
+ ld [rOBP1], a
+ call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same
+; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap
+ hlCoord 12, 0
+ ld bc, $707
+ call ClearScreenArea
+ call Delay3
+ xor a
+ ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon
+; replace ghost pic with Marowak in BG
+ ld a, MAROWAK
+ ld [wHPBarMaxHP], a
+ ld a, $1
+ ld [H_WHOSETURN], a
+ callab Func_79793
+ ; alternate between black and light grey 8 times.
+ ; this makes the ghost's body appear to flash
+ ld d, $80
+ call FlashSprite8Times
+.fadeOutGhostLoop
+ ld c, 10
+ call DelayFrames
+ ld a, [rOBP1]
+ sla a
+ sla a
+ ld [rOBP1], a
+ jr nz, .fadeOutGhostLoop
+ call ClearSprites
+ call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM
+ ld b, $e4
+.fadeInMarowakLoop
+ ld c, 10
+ call DelayFrames
+ ld a, [rOBP1]
+ srl b
+ rra
+ srl b
+ rra
+ ld [rOBP1], a
+ ld a, b
+ and a
+ jr nz, .fadeInMarowakLoop
+ ld a, $1
+ ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared
+ call Delay3
+ jp ClearSprites
+
+; copies a mon pic's from background VRAM to sprite VRAM and sets up OAM
+CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a)
+ ld de, vFrontPic
+ ld hl, vSprites
+ ld bc, 7 * 7
+ call CopyVideoData
+ ld a, $10
+ ld [W_BASECOORDY], a
+ ld a, $70
+ ld [W_BASECOORDX], a
+ ld hl, wOAMBuffer
+ ld bc, $606
+ ld d, $8
+.oamLoop
+ push bc
+ ld a, [W_BASECOORDY]
+ ld e, a
+.oamInnerLoop
+ ld a, e
+ add $8
+ ld e, a
+ ld [hli], a
+ ld a, [W_BASECOORDX]
+ ld [hli], a
+ ld a, d
+ ld [hli], a
+ ld a, $10 ; use OBP1
+ ld [hli], a
+ inc d
+ dec c
+ jr nz, .oamInnerLoop
+ inc d
+ ld a, [W_BASECOORDX]
+ add $8
+ ld [W_BASECOORDX], a
+ pop bc
+ dec b
+ jr nz, .oamLoop
+ ret
--- /dev/null
+++ b/engine/battle/init_battle_variables.asm
@@ -1,0 +1,40 @@
+InitBattleVariables: ; 525af (14:65af)
+ ld a, [hTilesetType]
+ ld [wd0d4], a
+ xor a
+ ld [wcd6a], a
+ ld [wBattleResult], a
+ ld hl, wcc2b
+ ld [hli], a
+ ld [hli], a
+ ld [hli], a
+ ld [hl], a
+ ld [wListScrollOffset], a
+ ld [wCriticalHitOrOHKO], a
+ ld [wBattleMonSpecies], a
+ ld [wPartyGainExpFlags], a
+ ld [wPlayerMonNumber], a
+ ld [wEscapedFromBattle], a
+ ld [wMapPalOffset], a
+ ld hl, wcf1d
+ ld [hli], a
+ ld [hl], a
+ ld hl, wccd3
+ ld b, $3c
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ inc a
+ ld [wccd9], a
+ ld a, [W_CURMAP]
+ cp SAFARI_ZONE_EAST
+ jr c, .notSafariBattle
+ cp SAFARI_ZONE_REST_HOUSE_1
+ jr nc, .notSafariBattle
+ ld a, $2 ; safari battle
+ ld [W_BATTLETYPE], a
+.notSafariBattle
+ ld hl, PlayBattleMusic
+ ld b, BANK(PlayBattleMusic)
+ jp Bankswitch
--- /dev/null
+++ b/engine/battle/link_battle_versus_text.asm
@@ -1,0 +1,23 @@
+; display "[player] VS [enemy]" text box with pokeballs representing their parties next to the names
+DisplayLinkBattleVersusTextBox: ; 372d6 (d:72d6)
+ call LoadTextBoxTilePatterns
+ hlCoord 3, 4
+ ld b, $7
+ ld c, $c
+ call TextBoxBorder
+ hlCoord 4, 5
+ ld de, wPlayerName
+ call PlaceString
+ hlCoord 4, 10
+ ld de, wLinkEnemyTrainerName
+ call PlaceString
+; place bold "VS" tiles between the names
+ hlCoord 9, 8
+ ld a, $69
+ ld [hli], a
+ ld [hl], $6a
+ xor a
+ ld [wUpdateSpritesEnabled], a
+ callab SetupPlayerAndEnemyPokeballs
+ ld c, 150
+ jp DelayFrames
--- /dev/null
+++ b/engine/battle/moveEffects/conversion_effect.asm
@@ -1,0 +1,34 @@
+ConversionEffect_: ; 139a3 (4:79a3)
+ ld hl, wEnemyMonType1
+ ld de, wBattleMonType1
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, [W_ENEMYBATTSTATUS1]
+ jr z, .asm_139b8
+ push hl
+ ld h, d
+ ld l, e
+ pop de
+ ld a, [W_PLAYERBATTSTATUS1]
+.asm_139b8
+ bit Invulnerable, a ; is mon immune to typical attacks (dig/fly)
+ jr nz, PrintButItFailedText
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ ld hl, PlayCurrentMoveAnimation
+ call CallBankF
+ ld hl, ConvertedTypeText
+ jp PrintText
+
+ConvertedTypeText: ; 139cd (4:79cd)
+ TX_FAR _ConvertedTypeText
+ db "@"
+
+PrintButItFailedText: ; 139d2 (4:79d2)
+ ld hl, PrintButItFailedText_
+CallBankF: ; 139d5 (4:79d5)
+ ld b, BANK(PrintButItFailedText_)
+ jp Bankswitch
--- /dev/null
+++ b/engine/battle/moveEffects/drain_hp_effect.asm
@@ -1,0 +1,104 @@
+DrainHPEffect_: ; 783f (1:783f)
+ ld hl, W_DAMAGE
+ ld a, [hl]
+ srl a ; divide damage by 2
+ ld [hli], a
+ ld a, [hl]
+ rr a
+ ld [hld], a
+ or [hl] ; is damage 0?
+ jr nz, .getAttackerHP
+; if damage is 0, increase to 1 so that the attacker gains at least 1 HP
+ inc hl
+ inc [hl]
+.getAttackerHP
+ ld hl, wBattleMonHP
+ ld de, wBattleMonMaxHP
+ ld a, [H_WHOSETURN]
+ and a
+ jp z, .addDamageToAttackerHP
+ ld hl, wEnemyMonHP
+ ld de, wEnemyMonMaxHP
+.addDamageToAttackerHP
+ ld bc, wHPBarOldHP+1
+; copy current HP to wHPBarOldHP
+ ld a, [hli]
+ ld [bc], a
+ ld a, [hl]
+ dec bc
+ ld [bc], a
+; copy max HP to wHPBarMaxHP
+ ld a, [de]
+ dec bc
+ ld [bc], a
+ inc de
+ ld a, [de]
+ dec bc
+ ld [bc], a
+; add damage to attacker's HP and copy new HP to wHPBarNewHP
+ ld a, [W_DAMAGE + 1]
+ ld b, [hl]
+ add b
+ ld [hld], a
+ ld [wHPBarNewHP], a
+ ld a, [W_DAMAGE]
+ ld b, [hl]
+ adc b
+ ld [hli], a
+ ld [wHPBarNewHP+1], a
+ jr c, .capToMaxHP ; if HP > 65,535, cap to max HP
+; compare HP with max HP
+ ld a, [hld]
+ ld b, a
+ ld a, [de]
+ dec de
+ sub b
+ ld a, [hli]
+ ld b, a
+ ld a, [de]
+ inc de
+ sbc b
+ jr nc, .next
+.capToMaxHP
+ ld a, [de]
+ ld [hld], a
+ ld [wHPBarNewHP], a
+ dec de
+ ld a, [de]
+ ld [hli], a
+ ld [wHPBarNewHP+1], a
+ inc de
+.next
+ ld a, [H_WHOSETURN]
+ and a
+ hlCoord 10, 9
+ ld a, $1
+ jr z, .next2
+ hlCoord 2, 2
+ xor a
+.next2
+ ld [wHPBarType], a
+ predef UpdateHPBar2
+ predef DrawPlayerHUDAndHPBar
+ predef DrawEnemyHUDAndHPBar
+ callab ReadPlayerMonCurHPAndStatus
+ ld hl, SuckedHealthText
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, [W_PLAYERMOVEEFFECT]
+ jr z, .next3
+ ld a, [W_ENEMYMOVEEFFECT]
+.next3
+ cp DREAM_EATER_EFFECT
+ jr nz, .printText
+ ld hl, DreamWasEatenText
+.printText
+ jp PrintText
+
+SuckedHealthText: ; 78dc (1:78dc)
+ TX_FAR _SuckedHealthText
+ db "@"
+
+DreamWasEatenText: ; 78e1 (1:78e1)
+ TX_FAR _DreamWasEatenText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/focus_energy_effect.asm
@@ -1,0 +1,24 @@
+FocusEnergyEffect_: ; 27f86 (9:7f86)
+ ld hl, W_PLAYERBATTSTATUS2
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .notEnemy
+ ld hl, W_ENEMYBATTSTATUS2
+.notEnemy
+ bit GettingPumped, [hl] ; is mon already using focus energy?
+ jr nz, .alreadyUsing
+ set GettingPumped, [hl] ; mon is now using focus energy
+ callab PlayCurrentMoveAnimation
+ ld hl, GettingPumpedText
+ jp PrintText
+.alreadyUsing
+ ld c, $32
+ call DelayFrames
+ ld hl, PrintButItFailedText_
+ ld b, BANK(PrintButItFailedText_)
+ jp Bankswitch
+
+GettingPumpedText: ; 27fb3 (9:7fb3)
+ db $0a
+ TX_FAR _GettingPumpedText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/haze_effect.asm
@@ -1,0 +1,76 @@
+HazeEffect_: ; 139da (4:79da)
+ ld a, $7
+ ld hl, wPlayerMonAttackMod
+ call ResetStatMods
+ ld hl, wEnemyMonAttackMod
+ call ResetStatMods
+ ld hl, wPlayerMonUnmodifiedAttack
+ ld de, wBattleMonAttack
+ call ResetStats
+ ld hl, wEnemyMonUnmodifiedAttack
+ ld de, wEnemyMonAttack
+ call ResetStats
+ ld hl, wEnemyMonStatus
+ ld de, wEnemySelectedMove
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .asm_13a09
+ ld hl, wBattleMonStatus
+ dec de
+
+.asm_13a09
+ ld a, [hl]
+ ld [hl], $0
+ and $27
+ jr z, .asm_13a13
+ ld a, $ff
+ ld [de], a
+
+.asm_13a13
+ xor a
+ ld [W_PLAYERDISABLEDMOVE], a
+ ld [W_ENEMYDISABLEDMOVE], a
+ ld hl, wccee
+ ld [hli], a
+ ld [hl], a
+ ld hl, W_PLAYERBATTSTATUS1
+ call CureStatuses
+ ld hl, W_ENEMYBATTSTATUS1
+ call CureStatuses
+ ld hl, PlayCurrentMoveAnimation
+ call CallBankF
+ ld hl, StatusChangesEliminatedText
+ jp PrintText
+
+CureStatuses: ; 13a37 (4:7a37)
+ res Confused, [hl]
+ inc hl ; BATTSTATUS2
+ ld a, [hl]
+ and (1 << UsingRage) | (1 << NeedsToRecharge) | (1 << HasSubstituteUp) | (1 << 3) ; clear all but these from BATTSTATUS2
+ ld [hli], a ; BATTSTATUS3
+ ld a, [hl]
+ and %11110000 | (1 << Transformed) ; clear Bad Poison, Reflect and Light Screen statuses
+ ld [hl], a
+ ret
+
+ResetStatMods: ; 13a43 (4:7a43)
+ ld b, $8
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ ret
+
+ResetStats: ; 13a4a (4:7a4a)
+ ld b, $8
+.loop
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .loop
+ ret
+
+StatusChangesEliminatedText: ; 13a53 (4:7a53)
+ TX_FAR _StatusChangesEliminatedText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/heal_effect.asm
@@ -1,0 +1,116 @@
+HealEffect_: ; 3b9ec (e:79ec)
+ ld a, [H_WHOSETURN]
+ and a
+ ld de, wBattleMonHP
+ ld hl, wBattleMonMaxHP
+ ld a, [W_PLAYERMOVENUM]
+ jr z, .asm_3ba03
+ ld de, wEnemyMonHP
+ ld hl, wEnemyMonMaxHP
+ ld a, [W_ENEMYMOVENUM]
+.asm_3ba03
+ ld b, a
+ ld a, [de]
+ cp [hl]
+ inc de
+ inc hl
+ ld a, [de]
+ sbc [hl]
+ jp z, .failed
+ ld a, b
+ cp REST
+ jr nz, .asm_3ba37
+ push hl
+ push de
+ push af
+ ld c, 50
+ call DelayFrames
+ ld hl, wBattleMonStatus
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .asm_3ba25
+ ld hl, wEnemyMonStatus
+.asm_3ba25
+ ld a, [hl]
+ and a
+ ld [hl], 2 ; Number of turns from Rest
+ ld hl, StartedSleepingEffect
+ jr z, .asm_3ba31
+ ld hl, FellAsleepBecameHealthyText
+.asm_3ba31
+ call PrintText
+ pop af
+ pop de
+ pop hl
+.asm_3ba37
+ ld a, [hld]
+ ld [wHPBarMaxHP], a
+ ld c, a
+ ld a, [hl]
+ ld [wHPBarMaxHP+1], a
+ ld b, a
+ jr z, .asm_3ba47
+ srl b
+ rr c
+.asm_3ba47
+ ld a, [de]
+ ld [wHPBarOldHP], a
+ add c
+ ld [de], a
+ ld [wHPBarNewHP], a
+ dec de
+ ld a, [de]
+ ld [wHPBarOldHP+1], a
+ adc b
+ ld [de], a
+ ld [wHPBarNewHP+1], a
+ inc hl
+ inc de
+ ld a, [de]
+ dec de
+ sub [hl]
+ dec hl
+ ld a, [de]
+ sbc [hl]
+ jr c, .asm_3ba6f
+ ld a, [hli]
+ ld [de], a
+ ld [wHPBarNewHP+1], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ ld [wHPBarNewHP], a
+.asm_3ba6f
+ ld hl, PlayCurrentMoveAnimation
+ call BankswitchEtoF
+ ld a, [H_WHOSETURN]
+ and a
+ hlCoord 10, 9
+ ld a, $1
+ jr z, .asm_3ba83
+ hlCoord 2, 2
+ xor a
+.asm_3ba83
+ ld [wHPBarType], a
+ predef UpdateHPBar2
+ ld hl, DrawHUDsAndHPBars
+ call BankswitchEtoF
+ ld hl, RegainedHealthText
+ jp PrintText
+.failed
+ ld c, 50
+ call DelayFrames
+ ld hl, PrintButItFailedText_
+ jp BankswitchEtoF
+
+StartedSleepingEffect: ; 3baa2 (e:7aa2)
+ TX_FAR _StartedSleepingEffect
+ db "@"
+
+FellAsleepBecameHealthyText: ; 3baa7 (e:7aa7)
+ TX_FAR _FellAsleepBecameHealthyText
+ db "@"
+
+RegainedHealthText: ; 3baac (e:7aac)
+ TX_FAR _RegainedHealthText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/leech_seed_effect.asm
@@ -1,0 +1,39 @@
+LeechSeedEffect_: ; 2bea9 (a:7ea9)
+ callab MoveHitTest
+ ld a, [W_MOVEMISSED] ; W_MOVEMISSED
+ and a
+ jr nz, .asm_2bee7
+ ld hl, W_ENEMYBATTSTATUS2 ; W_ENEMYBATTSTATUS2
+ ld de, wEnemyMonType1 ; wcfea (aliases: wEnemyMonType)
+ ld a, [H_WHOSETURN] ; $fff3
+ and a
+ jr z, .asm_2bec8
+ ld hl, W_PLAYERBATTSTATUS2 ; W_PLAYERBATTSTATUS2
+ ld de, wBattleMonType1 ; wd019 (aliases: wBattleMonType)
+.asm_2bec8
+ ld a, [de]
+ cp GRASS
+ jr z, .asm_2bee7
+ inc de
+ ld a, [de]
+ cp GRASS
+ jr z, .asm_2bee7
+ bit Seeded, [hl]
+ jr nz, .asm_2bee7
+ set Seeded, [hl]
+ callab PlayCurrentMoveAnimation
+ ld hl, WasSeededText ; $7ef2
+ jp PrintText
+.asm_2bee7
+ ld c, $32
+ call DelayFrames
+ ld hl, EvadedAttackText ; $7ef7
+ jp PrintText
+
+WasSeededText: ; 2bef2 (a:7ef2)
+ TX_FAR _WasSeededText
+ db "@"
+
+EvadedAttackText: ; 2bef7 (a:7ef7)
+ TX_FAR _EvadedAttackText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/mist_effect.asm
@@ -1,0 +1,21 @@
+MistEffect_: ; 33f2b (c:7f2b)
+ ld hl, W_PLAYERBATTSTATUS2
+ ld a, [$fff3]
+ and a
+ jr z, .asm_33f36
+ ld hl, W_ENEMYBATTSTATUS2
+.asm_33f36
+ bit ProtectedByMist, [hl] ; is mon protected by mist?
+ jr nz, .asm_33f4a
+ set ProtectedByMist, [hl] ; mon is now protected by mist
+ callab PlayCurrentMoveAnimation
+ ld hl, ShroudedInMistText
+ jp PrintText
+.asm_33f4a
+ ld hl, PrintButItFailedText_
+ ld b, BANK(PrintButItFailedText_)
+ jp Bankswitch
+
+ShroudedInMistText: ; 33f52 (c:7f52)
+ TX_FAR _ShroudedInMistText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/one_hit_ko_effect.asm
@@ -1,0 +1,36 @@
+OneHitKOEffect_: ; 33f57 (c:7f57)
+ ld hl, W_DAMAGE
+ xor a
+ ld [hli], a
+ ld [hl], a ; set the damage output to zero
+ dec a
+ ld [wCriticalHitOrOHKO], a
+ ld hl, wBattleMonSpeed + 1
+ ld de, wEnemyMonSpeed + 1
+ ld a, [H_WHOSETURN] ; $fff3
+ and a
+ jr z, .asm_33f72
+ ld hl, wEnemyMonSpeed + 1
+ ld de, wBattleMonSpeed + 1
+.asm_33f72
+ ld a, [de]
+ dec de
+ ld b, a
+ ld a, [hld]
+ sub b
+ ld a, [de]
+ ld b, a
+ ld a, [hl]
+ sbc b
+ jr c, .asm_33f8a
+ ld hl, W_DAMAGE
+ ld a, $ff
+ ld [hli], a
+ ld [hl], a
+ ld a, $2
+ ld [wCriticalHitOrOHKO], a
+ ret
+.asm_33f8a
+ ld a, $1
+ ld [W_MOVEMISSED], a
+ ret
--- /dev/null
+++ b/engine/battle/moveEffects/paralyze_effect.asm
@@ -1,0 +1,53 @@
+ParalyzeEffect_: ; 52601 (14:6601)
+ ld hl, wEnemyMonStatus
+ ld de, W_PLAYERMOVETYPE
+ ld a, [H_WHOSETURN]
+ and a
+ jp z, .next
+ ld hl, wBattleMonStatus
+ ld de, W_ENEMYMOVETYPE
+.next
+ ld a, [hl]
+ and a ; does the target already have a status ailment?
+ jr nz, .didntAffect
+; check if the target is immune due to types
+ ld a, [de]
+ cp ELECTRIC
+ jr nz, .hitTest
+ ld b, h
+ ld c, l
+ inc bc
+ ld a, [bc]
+ cp GROUND
+ jr z, .doesntAffect
+ inc bc
+ ld a, [bc]
+ cp GROUND
+ jr z, .doesntAffect
+.hitTest
+ push hl
+ callab MoveHitTest
+ pop hl
+ ld a, [W_MOVEMISSED]
+ and a
+ jr nz, .didntAffect
+ set PAR, [hl]
+ callab QuarterSpeedDueToParalysis
+ ld c, 30
+ call DelayFrames
+ callab PlayCurrentMoveAnimation
+ ld hl, PrintMayNotAttackText
+ ld b, BANK(PrintMayNotAttackText)
+ jp Bankswitch
+.didntAffect
+ ld c, 50
+ call DelayFrames
+ ld hl, PrintDidntAffectText
+ ld b, BANK(PrintDidntAffectText)
+ jp Bankswitch
+.doesntAffect
+ ld c, 50
+ call DelayFrames
+ ld hl, PrintDoesntAffectText
+ ld b, BANK(PrintDoesntAffectText)
+ jp Bankswitch
--- /dev/null
+++ b/engine/battle/moveEffects/pay_day_effect.asm
@@ -1,0 +1,43 @@
+PayDayEffect_ ; 2feb8 (b:7eb8)
+ xor a
+ ld hl, wcd6d
+ ld [hli], a
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, [wBattleMonLevel]
+ jr z, .asm_2fec8
+ ld a, [wEnemyMonLevel]
+.asm_2fec8
+ add a
+ ld [H_DIVIDEND + 3], a
+ xor a
+ ld [H_DIVIDEND], a
+ ld [H_DIVIDEND + 1], a
+ ld [H_DIVIDEND + 2], a
+ ld a, $64
+ ld [H_DIVISOR], a
+ ld b, $4
+ call Divide
+ ld a, [H_QUOTIENT + 3]
+ ld [hli], a
+ ld a, [H_REMAINDER]
+ ld [H_DIVIDEND + 3], a
+ ld a, $a
+ ld [H_DIVISOR], a
+ ld b, $4
+ call Divide
+ ld a, [H_QUOTIENT + 3]
+ swap a
+ ld b, a
+ ld a, [H_REMAINDER]
+ add b
+ ld [hl], a
+ ld de, wTotalPayDayMoney + 2
+ ld c, $3
+ predef AddBCDPredef
+ ld hl, CoinsScatteredText
+ jp PrintText
+
+CoinsScatteredText: ; 2ff04 (b:7f04)
+ TX_FAR _CoinsScatteredText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/recoil_effect.asm
@@ -1,0 +1,68 @@
+RecoilEffect_: ; 1392c (4:792c)
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, [W_PLAYERMOVENUM]
+ ld hl, wBattleMonMaxHP
+ jr z, .asm_1393d
+ ld a, [W_ENEMYMOVENUM]
+ ld hl, wEnemyMonMaxHP
+.asm_1393d
+ ld d, a
+ ld a, [W_DAMAGE]
+ ld b, a
+ ld a, [W_DAMAGE + 1]
+ ld c, a
+ srl b
+ rr c
+ ld a, d
+ cp STRUGGLE
+ jr z, .asm_13953
+ srl b
+ rr c
+.asm_13953
+ ld a, b
+ or c
+ jr nz, .asm_13958
+ inc c
+.asm_13958
+ ld a, [hli]
+ ld [wHPBarMaxHP+1], a
+ ld a, [hl]
+ ld [wHPBarMaxHP], a
+ push bc
+ ld bc, $fff2
+ add hl, bc
+ pop bc
+ ld a, [hl]
+ 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, .asm_13982
+ xor a
+ ld [hli], a
+ ld [hl], a
+ ld hl, wHPBarNewHP
+ ld [hli], a
+ ld [hl], a
+.asm_13982
+ hlCoord 10, 9
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, $1
+ jr z, .asm_13990
+ hlCoord 2, 2
+ xor a
+.asm_13990
+ ld [wHPBarType], a
+ predef UpdateHPBar2
+ ld hl, HitWithRecoilText
+ jp PrintText
+HitWithRecoilText: ; 1399e (4:799e)
+ TX_FAR _HitWithRecoilText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/reflect_light_screen_effect.asm
@@ -1,0 +1,45 @@
+ReflectLightScreenEffect_: ; 3bb97 (e:7b97)
+ ld hl, W_PLAYERBATTSTATUS3
+ ld de, W_PLAYERMOVEEFFECT
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .asm_3bba8
+ ld hl, W_ENEMYBATTSTATUS3
+ ld de, W_ENEMYMOVEEFFECT
+.asm_3bba8
+ ld a, [de]
+ cp LIGHT_SCREEN_EFFECT
+ jr nz, .reflect
+ bit HasLightScreenUp, [hl] ; is mon already protected by light screen?
+ jr nz, .moveFailed
+ set HasLightScreenUp, [hl] ; mon is now protected by light screen
+ ld hl, LightScreenProtectedText
+ jr .asm_3bbc1
+.reflect
+ bit HasReflectUp, [hl] ; is mon already protected by reflect?
+ jr nz, .moveFailed
+ set HasReflectUp, [hl] ; mon is now protected by reflect
+ ld hl, ReflectGainedArmorText
+.asm_3bbc1
+ push hl
+ ld hl, PlayCurrentMoveAnimation
+ call BankswitchEtoF
+ pop hl
+ jp PrintText
+.moveFailed
+ ld c, $32
+ call DelayFrames
+ ld hl, PrintButItFailedText_
+ jp BankswitchEtoF
+
+LightScreenProtectedText: ; 3bbd7 (e:7bd7)
+ TX_FAR _LightScreenProtectedText
+ db "@"
+
+ReflectGainedArmorText: ; 3bbdc (e:7bdc)
+ TX_FAR _ReflectGainedArmorText
+ db "@"
+
+BankswitchEtoF: ; 3bbe1 (e:7be1)
+ ld b, BANK(BattleCore)
+ jp Bankswitch
--- /dev/null
+++ b/engine/battle/moveEffects/substitute_effect.asm
@@ -1,0 +1,77 @@
+SubstituteEffect_: ; 17dad (5:7dad)
+ ld c, 50
+ call DelayFrames
+ ld hl, wBattleMonMaxHP
+ ld de, wPlayerSubstituteHP
+ ld bc, W_PLAYERBATTSTATUS2
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .notEnemy
+ ld hl, wEnemyMonMaxHP
+ ld de, wEnemySubstituteHP
+ ld bc, W_ENEMYBATTSTATUS2
+.notEnemy
+ ld a, [bc] ;load flags
+ bit HasSubstituteUp, a ;user already has substitute?
+ jr nz, .alreadyHasSubstitute ;skip this code if so
+ ;user doesn't have a substitute [yet]
+ push bc
+ ld a, [hli] ;load max hp
+ ld b, [hl]
+ srl a ;max hp / 4, [quarter health to remove from user]
+ rr b
+ srl a
+ rr b
+ push de
+ ld de, wBattleMonHP - wBattleMonMaxHP
+ add hl, de ; point hl to current HP
+ pop de
+ ld a, b
+ ld [de], a ;save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has]
+ ld a, [hld] ;load current hp
+ sub b ;subtract [max hp / 4]
+ ld d, a ;save low byte result in D
+ ld a, [hl]
+ sbc a, 0 ;borrow from high byte if needed
+ pop bc
+ jr c, .notEnoughHP ;underflow means user would be left with negative health
+ ;bug: note since it only brances on carry, it will possibly leave user with 0HP
+.userHasZeroOrMoreHP
+ ldi [hl], a ;store high byte HP
+ ld [hl], d ;store low byte HP
+ ld h, b
+ ld l, c
+ set HasSubstituteUp, [hl] ;set bit 4 of flags, user now has substitute
+ ld a, [W_OPTIONS] ;load options
+ bit 7, a ;battle animation is enabled?
+ ld hl, PlayCurrentMoveAnimation ;animation enabled: 0F:7BA8
+ ld b, BANK(PlayCurrentMoveAnimation)
+ jr z, .animationEnabled
+ ld hl, AnimationSubstitute ;animation disabled: 1E:56E0
+ ld b, BANK(AnimationSubstitute)
+.animationEnabled
+ call Bankswitch ;jump to routine depending on animation setting
+ ld hl, SubstituteText
+ call PrintText
+ ld hl, DrawHUDsAndHPBars
+ ld b, BANK(DrawHUDsAndHPBars)
+ jp Bankswitch
+.alreadyHasSubstitute
+ ld hl, HasSubstituteText
+ jr .printText
+.notEnoughHP
+ ld hl, TooWeakSubstituteText
+.printText
+ jp PrintText
+
+SubstituteText: ; 17e1d (5:7e1d)
+ TX_FAR _SubstituteText
+ db "@"
+
+HasSubstituteText: ; 17e22 (5:7e22)
+ TX_FAR _HasSubstituteText
+ db "@"
+
+TooWeakSubstituteText: ; 17e27 (5:7e27)
+ TX_FAR _TooWeakSubstituteText
+ db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/transform_effect.asm
@@ -1,0 +1,138 @@
+TransformEffect_: ; 3bab1 (e:7ab1)
+ ld hl, wBattleMonSpecies
+ ld de, wEnemyMonSpecies
+ ld bc, W_ENEMYBATTSTATUS3
+ ld a, [W_ENEMYBATTSTATUS1]
+ ld a, [H_WHOSETURN]
+ and a
+ jr nz, .asm_3bad1
+ ld hl, wEnemyMonSpecies
+ ld de, wBattleMonSpecies
+ ld bc, W_PLAYERBATTSTATUS3
+ ld [wPlayerMoveListIndex], a
+ ld a, [W_PLAYERBATTSTATUS1]
+.asm_3bad1
+ bit Invulnerable, a ; is mon invulnerable to typical attacks? (fly/dig)
+ jp nz, .failed
+ push hl
+ push de
+ push bc
+ ld hl, W_PLAYERBATTSTATUS2
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .asm_3bae4
+ ld hl, W_ENEMYBATTSTATUS2
+.asm_3bae4
+ bit HasSubstituteUp, [hl]
+ push af
+ ld hl, Func_79747
+ ld b, BANK(Func_79747)
+ call nz, Bankswitch
+ ld a, [W_OPTIONS]
+ add a
+ ld hl, PlayCurrentMoveAnimation
+ ld b, BANK(PlayCurrentMoveAnimation)
+ jr nc, .asm_3baff
+ ld hl, AnimationTransformMon
+ ld b, BANK(AnimationTransformMon)
+.asm_3baff
+ call Bankswitch
+ ld hl, Func_79771
+ ld b, BANK(Func_79771)
+ pop af
+ call nz, Bankswitch
+ pop bc
+ ld a, [bc]
+ set Transformed, a
+ ld [bc], a
+ pop de
+ pop hl
+ push hl
+ ld a, [hl]
+ ld [de], a
+ ld bc, $5
+ add hl, bc
+ inc de
+ inc de
+ inc de
+ inc de
+ inc de
+ inc bc
+ inc bc
+ call CopyData
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .asm_3bb32
+ ld a, [de]
+ ld [wcceb], a
+ inc de
+ ld a, [de]
+ ld [wccec], a
+ dec de
+.asm_3bb32
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hli]
+ ld [de], a
+ inc de
+ inc hl
+ inc hl
+ inc hl
+ inc de
+ inc de
+ inc de
+ ld bc, $8
+ call CopyData
+ ld bc, $ffef
+ add hl, bc
+ ld b, $4
+.asm_3bb4a
+ ld a, [hli]
+ and a
+ jr z, .asm_3bb57
+ ld a, $5
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .asm_3bb4a
+ jr .asm_3bb5d
+.asm_3bb57
+ xor a
+ ld [de], a
+ inc de
+ dec b
+ jr nz, .asm_3bb57
+.asm_3bb5d
+ pop hl
+ ld a, [hl]
+ ld [wd11e], a
+ call GetMonName
+ ld hl, wEnemyMonUnmodifiedAttack
+ ld de, wPlayerMonUnmodifiedAttack
+ call .copyBasedOnTurn
+ ld hl, wEnemyMonStatMods
+ ld de, wPlayerMonStatMods
+ call .copyBasedOnTurn
+ ld hl, TransformedText
+ jp PrintText
+
+.copyBasedOnTurn
+ ld a, [H_WHOSETURN]
+ and a
+ jr z, .asm_3bb86
+ push hl
+ ld h, d
+ ld l, e
+ pop de
+.asm_3bb86
+ ld bc, $8
+ jp CopyData
+
+.failed
+ ld hl, PrintButItFailedText_
+ jp BankswitchEtoF
+
+TransformedText: ; 3bb92 (e:7b92)
+ TX_FAR _TransformedText
+ db "@"
--- /dev/null
+++ b/engine/battle/print_type.asm
@@ -1,0 +1,52 @@
+; [wd0b5] = pokemon ID
+; hl = dest addr
+PrintMonType: ; 27d6b (9:7d6b)
+ call GetPredefRegisters
+ push hl
+ call GetMonHeader
+ pop hl
+ push hl
+ ld a, [W_MONHTYPE1]
+ call PrintType
+ ld a, [W_MONHTYPE1]
+ ld b, a
+ ld a, [W_MONHTYPE2]
+ cp b
+ pop hl
+ jr z, EraseType2Text
+ ld bc, SCREEN_WIDTH * 2
+ add hl, bc
+
+; a = type
+; hl = dest addr
+PrintType: ; 27d89 (9:7d89)
+ push hl
+ jr PrintType_
+
+; erase "TYPE2/" if the mon only has 1 type
+EraseType2Text: ; 27d8c (9:7d8c)
+ ld a, " "
+ ld bc, $13
+ add hl, bc
+ ld bc, $6
+ jp FillMemory
+
+PrintMoveType: ; 27d98 (9:7d98)
+ call GetPredefRegisters
+ push hl
+ ld a, [W_PLAYERMOVETYPE]
+; fall through
+
+PrintType_: ; 27d9f (9:7d9f)
+ add a
+ ld hl, TypeNames
+ ld e, a
+ ld d, $0
+ add hl, de
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+ pop hl
+ jp PlaceString
+
+INCLUDE "text/type_names.asm"
--- /dev/null
+++ b/engine/battle/read_trainer_party.asm
@@ -1,0 +1,164 @@
+ReadTrainer: ; 39c53 (e:5c53)
+
+; don't change any moves in a link battle
+ ld a,[wLinkState]
+ and a
+ ret nz
+
+; set [wEnemyPartyCount] to 0, [wEnemyPartyMons] to FF
+; XXX first is total enemy pokemon?
+; XXX second is species of first pokemon?
+ ld hl,wEnemyPartyCount
+ xor a
+ ld [hli],a
+ dec a
+ ld [hl],a
+
+; get the pointer to trainer data for this class
+ ld a,[W_CUROPPONENT]
+ sub $C9 ; convert value from pokemon to trainer
+ add a,a
+ ld hl,TrainerDataPointers
+ ld c,a
+ ld b,0
+ add hl,bc ; hl points to trainer class
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ ld a,[W_TRAINERNO]
+ ld b,a
+; At this point b contains the trainer number,
+; and hl points to the trainer class.
+; Our next task is to iterate through the trainers,
+; decrementing b each time, until we get to the right one.
+.outer
+ dec b
+ jr z,.IterateTrainer
+.inner
+ ld a,[hli]
+ and a
+ jr nz,.inner
+ jr .outer
+
+; if the first byte of trainer data is FF,
+; - each pokemon has a specific level
+; (as opposed to the whole team being of the same level)
+; - if [W_LONEATTACKNO] != 0, one pokemon on the team has a special move
+; else the first byte is the level of every pokemon on the team
+.IterateTrainer
+ ld a,[hli]
+ cp $FF ; is the trainer special?
+ jr z,.SpecialTrainer ; if so, check for special moves
+ ld [W_CURENEMYLVL],a
+.LoopTrainerData
+ ld a,[hli]
+ and a ; have we reached the end of the trainer data?
+ jr z,.FinishUp
+ ld [wcf91],a ; write species somewhere (XXX why?)
+ ld a,1
+ ld [wcc49],a
+ push hl
+ call AddPartyMon
+ pop hl
+ jr .LoopTrainerData
+.SpecialTrainer
+; if this code is being run:
+; - each pokemon has a specific level
+; (as opposed to the whole team being of the same level)
+; - if [W_LONEATTACKNO] != 0, one pokemon on the team has a special move
+ ld a,[hli]
+ and a ; have we reached the end of the trainer data?
+ jr z,.AddLoneMove
+ ld [W_CURENEMYLVL],a
+ ld a,[hli]
+ ld [wcf91],a
+ ld a,1
+ ld [wcc49],a
+ push hl
+ call AddPartyMon
+ pop hl
+ jr .SpecialTrainer
+.AddLoneMove
+; does the trainer have a single monster with a different move
+ ld a,[W_LONEATTACKNO] ; Brock is 01, Misty is 02, Erika is 04, etc
+ and a
+ jr z,.AddTeamMove
+ dec a
+ add a,a
+ ld c,a
+ ld b,0
+ ld hl,LoneMoves
+ add hl,bc
+ ld a,[hli]
+ ld d,[hl]
+ ld hl,wEnemyMon1Moves + 2
+ ld bc,wEnemyMon2 - wEnemyMon1
+ call AddNTimes
+ ld [hl],d
+ jr .FinishUp
+.AddTeamMove
+; check if our trainer's team has special moves
+
+; get trainer class number
+ ld a,[W_CUROPPONENT]
+ sub $C8
+ ld b,a
+ ld hl,TeamMoves
+
+; iterate through entries in TeamMoves, checking each for our trainer class
+.IterateTeamMoves
+ ld a,[hli]
+ cp b
+ jr z,.GiveTeamMoves ; is there a match?
+ inc hl ; if not, go to the next entry
+ inc a
+ jr nz,.IterateTeamMoves
+
+; no matches found. is this trainer champion rival?
+ ld a,b
+ cp SONY3
+ jr z,.ChampionRival
+ jr .FinishUp ; nope
+.GiveTeamMoves
+ ld a,[hl]
+ ld [wEnemyMon5Moves + 2],a
+ jr .FinishUp
+.ChampionRival ; give moves to his team
+
+; pidgeot
+ ld a,SKY_ATTACK
+ ld [wEnemyMon1Moves + 2],a
+
+; starter
+ ld a,[W_RIVALSTARTER]
+ cp STARTER3
+ ld b,MEGA_DRAIN
+ jr z,.GiveStarterMove
+ cp STARTER1
+ ld b,FIRE_BLAST
+ jr z,.GiveStarterMove
+ ld b,BLIZZARD ; must be squirtle
+.GiveStarterMove
+ ld a,b
+ ld [wEnemyMon6Moves + 2],a
+.FinishUp ; XXX this needs documenting
+ xor a ; clear D079-D07B
+ ld de,wd079
+ ld [de],a
+ inc de
+ ld [de],a
+ inc de
+ ld [de],a
+ ld a,[W_CURENEMYLVL]
+ ld b,a
+.LastLoop
+ ld hl,wd047
+ ld c,2
+ push bc
+ predef AddBCDPredef
+ pop bc
+ inc de
+ inc de
+ dec b
+ jr nz,.LastLoop
+ ret
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/save_trainer_name.asm
@@ -1,0 +1,112 @@
+SaveTrainerName: ; 27e4a (9:7e4a)
+ ld hl,TrainerNamePointers
+ ld a,[W_TRAINERCLASS]
+ dec a
+ ld c,a
+ ld b,0
+ add hl,bc
+ add hl,bc
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ ld de,wcd6d
+.CopyCharacter
+ ld a,[hli]
+ ld [de],a
+ inc de
+ cp "@"
+ jr nz,.CopyCharacter
+ ret
+
+TrainerNamePointers: ; 27e64 (9:7e64)
+; what is the point of these?
+ dw YoungsterName
+ dw BugCatcherName
+ dw LassName
+ dw W_TRAINERNAME
+ dw JrTrainerMName
+ dw JrTrainerFName
+ dw PokemaniacName
+ dw SuperNerdName
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw BurglarName
+ dw EngineerName
+ dw JugglerXName
+ dw W_TRAINERNAME
+ dw SwimmerName
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw BeautyName
+ dw W_TRAINERNAME
+ dw RockerName
+ dw JugglerName
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw BlackbeltName
+ dw W_TRAINERNAME
+ dw ProfOakName
+ dw ChiefName
+ dw ScientistName
+ dw W_TRAINERNAME
+ dw RocketName
+ dw CooltrainerMName
+ dw CooltrainerFName
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+ dw W_TRAINERNAME
+
+YoungsterName: ; 27ec2 (9:7ec2)
+ db "YOUNGSTER@"
+BugCatcherName: ; 27ecc (9:7ecc)
+ db "BUG CATCHER@"
+LassName: ; 27ed8 (9:7ed8)
+ db "LASS@"
+JrTrainerMName: ; 27edd (9:7edd)
+ db "JR.TRAINER♂@"
+JrTrainerFName: ; 27ee9 (9:7ee9)
+ db "JR.TRAINER♀@"
+PokemaniacName: ; 27ef5 (9:7ef5)
+ db "POKéMANIAC@"
+SuperNerdName: ; 27f00 (9:7f00)
+ db "SUPER NERD@"
+BurglarName: ; 27f0b (9:7f0b)
+ db "BURGLAR@"
+EngineerName: ; 27f13 (9:7f13)
+ db "ENGINEER@"
+JugglerXName: ; 27f1c (9:7f1c)
+ db "JUGGLER@"
+SwimmerName: ; 27f24 (9:7f24)
+ db "SWIMMER@"
+BeautyName: ; 27f2c (9:7f2c)
+ db "BEAUTY@"
+RockerName: ; 27f33 (9:7f33)
+ db "ROCKER@"
+JugglerName: ; 27f3a (9:7f3a)
+ db "JUGGLER@"
+BlackbeltName: ; 27f42 (9:7f42)
+ db "BLACKBELT@"
+ProfOakName: ; 27f4c (9:7f4c)
+ db "PROF.OAK@"
+ChiefName: ; 27f55 (9:7f55)
+ db "CHIEF@"
+ScientistName: ; 27f5b (9:7f5b)
+ db "SCIENTIST@"
+RocketName: ; 27f65 (9:7f65)
+ db "ROCKET@"
+CooltrainerMName: ; 27f6c (9:7f6c)
+ db "COOLTRAINER♂@"
+CooltrainerFName: ; 27f79 (9:7f79)
+ db "COOLTRAINER♀@"
--- /dev/null
+++ b/engine/battle/scale_sprites.asm
@@ -1,0 +1,85 @@
+; scales both uncompressed sprite chunks by two in every dimension (creating 2x2 output pixels per input pixel)
+; assumes that input sprite chunks are 4x4 tiles, and the rightmost and bottommost 4 pixels will be ignored
+; resulting in a 7*7 tile output sprite chunk
+ScaleSpriteByTwo: ; 2fe40 (b:7e40)
+ ld de, S_SPRITEBUFFER1 + (4*4*8) - 5 ; last byte of input data, last 4 rows already skipped
+ ld hl, S_SPRITEBUFFER0 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
+ call ScaleLastSpriteColumnByTwo ; last tile column is special case
+ call ScaleFirstThreeSpriteColumnsByTwo ; scale first 3 tile columns
+ ld de, S_SPRITEBUFFER2 + (4*4*8) - 5 ; last byte of input data, last 4 rows already skipped
+ ld hl, S_SPRITEBUFFER1 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
+ call ScaleLastSpriteColumnByTwo ; last tile column is special case
+
+ScaleFirstThreeSpriteColumnsByTwo: ; 2fe55 (b:7e55)
+ ld b, $3 ; 3 tile columns
+.columnLoop
+ ld c, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
+.columnInnerLoop
+ push bc
+ ld a, [de]
+ ld bc, -(7*8)+1 ; $ffc9, scale lower nybble and seek to previous output column
+ call ScalePixelsByTwo
+ ld a, [de]
+ dec de
+ swap a
+ ld bc, 7*8+1-2 ; $37, scale upper nybble and seek back to current output column and to the next 2 rows
+ call ScalePixelsByTwo
+ pop bc
+ dec c
+ jr nz, .columnInnerLoop
+ dec de
+ dec de
+ dec de
+ dec de
+ ld a, b
+ ld bc, -7*8 ; $ffc8, skip one output column (which has already been written along with the current one)
+ add hl, bc
+ ld b, a
+ dec b
+ jr nz, .columnLoop
+ ret
+
+ScaleLastSpriteColumnByTwo: ; 2fe7d (b:7e7d)
+ ld a, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
+ ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
+ ld bc, -1 ; $ffff
+.columnInnerLoop
+ ld a, [de]
+ dec de
+ swap a ; only high nybble contains information
+ call ScalePixelsByTwo
+ ld a, [H_SPRITEINTERLACECOUNTER] ; $ff8b
+ dec a
+ ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
+ jr nz, .columnInnerLoop
+ dec de ; skip last 4 rows of new column
+ dec de
+ dec de
+ dec de
+ ret
+
+; scales the given 4 bits in a (4x1 pixels) to 2 output bytes (8x2 pixels)
+; hl: destination pointer
+; bc: destination pointer offset (added after the two bytes have been written)
+ScalePixelsByTwo: ; 2fe97 (b:7e97)
+ push hl
+ and $f
+ ld hl, DuplicateBitsTable
+ add l
+ ld l, a
+ jr nc, .noCarry
+ inc h
+.noCarry
+ ld a, [hl]
+ pop hl
+ ld [hld], a ; write output byte twice to make it 2 pixels high
+ ld [hl], a
+ add hl, bc ; add offset
+ ret
+
+; repeats each input bit twice
+DuplicateBitsTable: ; 2fea8 (b:7ea8)
+ db $00, $03, $0c, $0f
+ db $30, $33, $3c, $3f
+ db $c0, $c3, $cc, $cf
+ db $f0, $f3, $fc, $ff
--- /dev/null
+++ b/engine/battle/scroll_draw_trainer_pic.asm
@@ -1,0 +1,50 @@
+_ScrollTrainerPicAfterBattle: ; 396d3 (e:56d3)
+; Load the enemy trainer's pic and scrolls it into
+; the screen from the right.
+ xor a
+ ld [wEnemyMonSpecies2], a
+ ld b, $1
+ call GoPAL_SET
+ callab _LoadTrainerPic
+ hlCoord 19, 0
+ ld c, $0
+.scrollLoop
+ inc c
+ ld a, c
+ cp 7
+ ret z
+ ld d, $0
+ push bc
+ push hl
+.drawTrainerPicLoop
+ call DrawTrainerPicColumn
+ inc hl
+ ld a, 7
+ add d
+ ld d, a
+ dec c
+ jr nz, .drawTrainerPicLoop
+ ld c, 4
+ call DelayFrames
+ pop hl
+ pop bc
+ dec hl
+ jr .scrollLoop
+
+; write one 7-tile column of the trainer pic to the tilemap
+DrawTrainerPicColumn: ; 39707 (e:5707)
+ push hl
+ push de
+ push bc
+ ld e, 7
+.loop
+ ld [hl], d
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ inc d
+ dec e
+ jr nz, .loop
+ pop bc
+ pop de
+ pop hl
+ ret
--- /dev/null
+++ b/engine/battle/trainer_ai.asm
@@ -1,0 +1,837 @@
+; creates a set of moves that may be used and returns its address in hl
+; unused slots are filled with 0, all used slots may be chosen with equal probability
+AIEnemyTrainerChooseMoves: ; 39719 (e:5719)
+ ld a, $a
+ ld hl, wHPBarMaxHP ; init temporary move selection array. Only the moves with the lowest numbers are chosen in the end
+ ld [hli], a ; move 1
+ ld [hli], a ; move 2
+ ld [hli], a ; move 3
+ ld [hl], a ; move 4
+ ld a, [W_ENEMYDISABLEDMOVE] ; forbid disabled move (if any)
+ swap a
+ and $f
+ jr z, .noMoveDisabled
+ ld hl, wHPBarMaxHP
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc ; advance pointer to forbidden move
+ ld [hl], $50 ; forbid (highly discourage) disabled move
+.noMoveDisabled
+ ld hl, TrainerClassMoveChoiceModifications ; 589B
+ ld a, [W_TRAINERCLASS]
+ ld b, a
+.loopTrainerClasses
+ dec b
+ jr z, .readTrainerClassData
+.loopTrainerClassData
+ ld a, [hli]
+ and a
+ jr nz, .loopTrainerClassData
+ jr .loopTrainerClasses
+.readTrainerClassData
+ ld a, [hl]
+ and a
+ jp z, .useOriginalMoveSet
+ push hl
+.nextMoveChoiceModification
+ pop hl
+ ld a, [hli]
+ and a
+ jr z, .loopFindMinimumEntries
+ push hl
+ ld hl, AIMoveChoiceModificationFunctionPointers ; $57a3
+ dec a
+ add a
+ ld c, a
+ ld b, $0
+ add hl, bc ; skip to pointer
+ ld a, [hli] ; read pointer into hl
+ ld h, [hl]
+ ld l, a
+ ld de, .nextMoveChoiceModification ; set return address
+ push de
+ jp [hl] ; execute modification function
+.loopFindMinimumEntries ; all entries will be decremented sequentially until one of them is zero
+ ld hl, wHPBarMaxHP ; temp move selection array
+ ld de, wEnemyMonMoves ; enemy moves
+ ld c, $4
+.loopDecrementEntries
+ ld a, [de]
+ inc de
+ and a
+ jr z, .loopFindMinimumEntries
+ dec [hl]
+ jr z, .minimumEntriesFound
+ inc hl
+ dec c
+ jr z, .loopFindMinimumEntries
+ jr .loopDecrementEntries
+.minimumEntriesFound
+ ld a, c
+.loopUndoPartialIteration ; undo last (partial) loop iteration
+ inc [hl]
+ dec hl
+ inc a
+ cp $5
+ jr nz, .loopUndoPartialIteration
+ ld hl, wHPBarMaxHP ; temp move selection array
+ ld de, wEnemyMonMoves ; enemy moves
+ ld c, $4
+.filterMinimalEntries ; all minimal entries now have value 1. All other slots will be disabled (move set to 0)
+ ld a, [de]
+ and a
+ jr nz, .moveExisting ; 0x3978a $1
+ ld [hl], a
+.moveExisting
+ ld a, [hl]
+ dec a
+ jr z, .slotWithMinimalValue
+ xor a
+ ld [hli], a ; disable move slot
+ jr .next
+.slotWithMinimalValue
+ ld a, [de]
+ ld [hli], a ; enable move slot
+.next
+ inc de
+ dec c
+ jr nz, .filterMinimalEntries
+ ld hl, wHPBarMaxHP ; use created temporary array as move set
+ ret
+.useOriginalMoveSet
+ ld hl, wEnemyMonMoves ; use original move set
+ ret
+
+AIMoveChoiceModificationFunctionPointers: ; 397a3 (e:57a3)
+ dw AIMoveChoiceModification1
+ dw AIMoveChoiceModification2
+ dw AIMoveChoiceModification3
+ dw AIMoveChoiceModification4 ; unused, does nothing
+
+; discourages moves that cause no damage but only a status ailment if player's mon already has one
+AIMoveChoiceModification1: ; 397ab (e:57ab)
+ ld a, [wBattleMonStatus]
+ and a
+ ret z ; return if no status ailment on player's mon
+ ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest)
+ ld de, wEnemyMonMoves ; enemy moves
+ ld b, NUM_MOVES + 1
+.nextMove
+ dec b
+ ret z ; processed all 4 moves
+ inc hl
+ ld a, [de]
+ and a
+ ret z ; no more moves in move set
+ inc de
+ call ReadMove
+ ld a, [W_ENEMYMOVEPOWER]
+ and a
+ jr nz, .nextMove
+ ld a, [W_ENEMYMOVEEFFECT]
+ push hl
+ push de
+ push bc
+ ld hl, StatusAilmentMoveEffects
+ ld de, $0001
+ call IsInArray
+ pop bc
+ pop de
+ pop hl
+ jr nc, .nextMove
+ ld a, [hl]
+ add $5 ; heavily discourage move
+ ld [hl], a
+ jr .nextMove
+
+StatusAilmentMoveEffects ; 57e2
+ db $01 ; unused sleep effect
+ db SLEEP_EFFECT
+ db POISON_EFFECT
+ db PARALYZE_EFFECT
+ db $FF
+
+; slightly encourage moves with specific effects.
+; in particular, stat-modifying moves and other move effects
+; that fall in-bewteen
+AIMoveChoiceModification2: ; 397e7 (e:57e7)
+ ld a, [wAILayer2Encouragement]
+ cp $1
+ ret nz
+ ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
+ ld de, wEnemyMonMoves ; enemy moves
+ ld b, NUM_MOVES + 1
+.nextMove
+ dec b
+ ret z ; processed all 4 moves
+ inc hl
+ ld a, [de]
+ and a
+ ret z ; no more moves in move set
+ inc de
+ call ReadMove
+ ld a, [W_ENEMYMOVEEFFECT]
+ cp ATTACK_UP1_EFFECT
+ jr c, .nextMove
+ cp BIDE_EFFECT
+ jr c, .preferMove
+ cp ATTACK_UP2_EFFECT
+ jr c, .nextMove
+ cp POISON_EFFECT
+ jr c, .preferMove
+ jr .nextMove
+.preferMove
+ dec [hl] ; sligthly encourage this move
+ jr .nextMove
+
+; encourages moves that are effective against the player's mon (even if non-damaging).
+; discourage damaging moves that are ineffective or not very effective against the player's mon,
+; unless there's no damaging move that deals at least neutral damage
+AIMoveChoiceModification3: ; 39817 (e:5817)
+ ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
+ ld de, wEnemyMonMoves ; enemy moves
+ ld b, $5
+.nextMove
+ dec b
+ ret z ; processed all 4 moves
+ inc hl
+ ld a, [de]
+ and a
+ ret z ; no more moves in move set
+ inc de
+ call ReadMove
+ push hl
+ push bc
+ push de
+ callab AIGetTypeEffectiveness
+ pop de
+ pop bc
+ pop hl
+ ld a, [wd11e]
+ cp $10
+ jr z, .nextMove
+ jr c, .notEffectiveMove
+ dec [hl] ; sligthly encourage this move
+ jr .nextMove
+.notEffectiveMove ; discourages non-effective moves if better moves are available
+ push hl
+ push de
+ push bc
+ ld a, [W_ENEMYMOVETYPE]
+ ld d, a
+ ld hl, wEnemyMonMoves ; enemy moves
+ ld b, NUM_MOVES + 1
+ ld c, $0
+.loopMoves
+ dec b
+ jr z, .done
+ ld a, [hli]
+ and a
+ jr z, .done
+ call ReadMove
+ ld a, [W_ENEMYMOVEEFFECT]
+ cp SUPER_FANG_EFFECT
+ jr z, .betterMoveFound ; Super Fang is considered to be a better move
+ cp SPECIAL_DAMAGE_EFFECT
+ jr z, .betterMoveFound ; any special damage moves are considered to be better moves
+ cp FLY_EFFECT
+ jr z, .betterMoveFound ; Fly is considered to be a better move
+ ld a, [W_ENEMYMOVETYPE]
+ cp d
+ jr z, .loopMoves
+ ld a, [W_ENEMYMOVEPOWER]
+ and a
+ jr nz, .betterMoveFound ; damaging moves of a different type are considered to be better moves
+ jr .loopMoves
+.betterMoveFound
+ ld c, a
+.done
+ ld a, c
+ pop bc
+ pop de
+ pop hl
+ and a
+ jr z, .nextMove
+ inc [hl] ; sligthly discourage this move
+ jr .nextMove
+AIMoveChoiceModification4: ; 39883 (e:5883)
+ ret
+
+ReadMove: ; 39884 (e:5884)
+ push hl
+ push de
+ push bc
+ dec a
+ ld hl,Moves
+ ld bc,6
+ call AddNTimes
+ ld de,W_ENEMYMOVENUM
+ call CopyData
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; move choice modification methods that are applied for each trainer class
+; 0 is sentinel value
+TrainerClassMoveChoiceModifications: ; 3989b (e:589b)
+ db 0 ; YOUNGSTER
+ db 1,0 ; BUG CATCHER
+ db 1,0 ; LASS
+ db 1,3,0 ; SAILOR
+ db 1,0 ; JR__TRAINER_M
+ db 1,0 ; JR__TRAINER_F
+ db 1,2,3,0; POKEMANIAC
+ db 1,2,0 ; SUPER_NERD
+ db 1,0 ; HIKER
+ db 1,0 ; BIKER
+ db 1,3,0 ; BURGLAR
+ db 1,0 ; ENGINEER
+ db 1,2,0 ; JUGGLER_X
+ db 1,3,0 ; FISHER
+ db 1,3,0 ; SWIMMER
+ db 0 ; CUE_BALL
+ db 1,0 ; GAMBLER
+ db 1,3,0 ; BEAUTY
+ db 1,2,0 ; PSYCHIC_TR
+ db 1,3,0 ; ROCKER
+ db 1,0 ; JUGGLER
+ db 1,0 ; TAMER
+ db 1,0 ; BIRD_KEEPER
+ db 1,0 ; BLACKBELT
+ db 1,0 ; SONY1
+ db 1,3,0 ; PROF_OAK
+ db 1,2,0 ; CHIEF
+ db 1,2,0 ; SCIENTIST
+ db 1,3,0 ; GIOVANNI
+ db 1,0 ; ROCKET
+ db 1,3,0 ; COOLTRAINER_M
+ db 1,3,0 ; COOLTRAINER_F
+ db 1,0 ; BRUNO
+ db 1,0 ; BROCK
+ db 1,3,0 ; MISTY
+ db 1,3,0 ; LT__SURGE
+ db 1,3,0 ; ERIKA
+ db 1,3,0 ; KOGA
+ db 1,3,0 ; BLAINE
+ db 1,3,0 ; SABRINA
+ db 1,2,0 ; GENTLEMAN
+ db 1,3,0 ; SONY2
+ db 1,3,0 ; SONY3
+ db 1,2,3,0; LORELEI
+ db 1,0 ; CHANNELER
+ db 1,0 ; AGATHA
+ db 1,3,0 ; LANCE
+
+INCLUDE "engine/battle/trainer_pic_money_pointers.asm"
+
+INCLUDE "text/trainer_names.asm"
+
+INCLUDE "engine/battle/bank_e_misc.asm"
+
+INCLUDE "engine/battle/read_trainer_party.asm"
+
+INCLUDE "data/trainer_moves.asm"
+
+INCLUDE "data/trainer_parties.asm"
+
+TrainerAI: ; 3a52e (e:652e)
+;XXX called at 34964, 3c342, 3c398
+ and a
+ ld a,[W_ISINBATTLE]
+ dec a
+ ret z ; if not a trainer, we're done here
+ ld a,[wLinkState]
+ cp LINK_STATE_BATTLING
+ ret z
+ ld a,[W_TRAINERCLASS] ; what trainer class is this?
+ dec a
+ ld c,a
+ ld b,0
+ ld hl,TrainerAIPointers
+ add hl,bc
+ add hl,bc
+ add hl,bc
+ ld a,[wAICount]
+ and a
+ ret z ; if no AI uses left, we're done here
+ inc hl
+ inc a
+ jr nz,.getpointer
+ dec hl
+ ld a,[hli]
+ ld [wAICount],a
+.getpointer
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ call Random
+ jp [hl]
+
+TrainerAIPointers: ; 3a55c (e:655c)
+; one entry per trainer class
+; first byte, number of times (per Pokémon) it can occur
+; next two bytes, pointer to AI subroutine for trainer class
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,JugglerAI ; juggler_x
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,JugglerAI ; juggler
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 2,BlackbeltAI ; blackbelt
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 1,GenericAI ; chief
+ dbw 3,GenericAI
+ dbw 1,GiovanniAI ; giovanni
+ dbw 3,GenericAI
+ dbw 2,CooltrainerMAI ; cooltrainerm
+ dbw 1,CooltrainerFAI ; cooltrainerf
+ dbw 2,BrunoAI ; bruno
+ dbw 5,BrockAI ; brock
+ dbw 1,MistyAI ; misty
+ dbw 1,LtSurgeAI ; surge
+ dbw 1,ErikaAI ; erika
+ dbw 2,KogaAI ; koga
+ dbw 2,BlaineAI ; blaine
+ dbw 1,SabrinaAI ; sabrina
+ dbw 3,GenericAI
+ dbw 1,Sony2AI ; sony2
+ dbw 1,Sony3AI ; sony3
+ dbw 2,LoreleiAI ; lorelei
+ dbw 3,GenericAI
+ dbw 2,AgathaAI ; agatha
+ dbw 1,LanceAI ; lance
+
+JugglerAI: ; 3a5e9 (e:65e9)
+ cp $40
+ ret nc
+ jp AISwitchIfEnoughMons
+
+BlackbeltAI: ; 3a5ef (e:65ef)
+ cp $20
+ ret nc
+ jp AIUseXAttack
+
+GiovanniAI: ; 3a5f5 (e:65f5)
+ cp $40
+ ret nc
+ jp AIUseGuardSpec
+
+CooltrainerMAI: ; 3a5fb (e:65fb)
+ cp $40
+ ret nc
+ jp AIUseXAttack
+
+CooltrainerFAI: ; 3a601 (e:6601)
+ cp $40
+ ld a,$A
+ call AICheckIfHPBelowFraction
+ jp c,AIUseHyperPotion
+ ld a,5
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AISwitchIfEnoughMons
+
+BrockAI: ; 3a614 (e:6614)
+; if his active monster has a status condition, use a full heal
+ ld a,[wEnemyMonStatus]
+ and a
+ ret z
+ jp AIUseFullHeal
+
+MistyAI: ; 3a61c (e:661c)
+ cp $40
+ ret nc
+ jp AIUseXDefend
+
+LtSurgeAI: ; 3a622 (e:6622)
+ cp $40
+ ret nc
+ jp AIUseXSpeed
+
+ErikaAI: ; 3a628 (e:6628)
+ cp $80
+ ret nc
+ ld a,$A
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUseSuperPotion
+
+KogaAI: ; 3a634 (e:6634)
+ cp $40
+ ret nc
+ jp AIUseXAttack
+
+BlaineAI: ; 3a63a (e:663a)
+ cp $40
+ ret nc
+ jp AIUseSuperPotion
+
+SabrinaAI: ; 3a640 (e:6640)
+ cp $40
+ ret nc
+ ld a,$A
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUseHyperPotion
+
+Sony2AI: ; 3a64c (e:664c)
+ cp $20
+ ret nc
+ ld a,5
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUsePotion
+
+Sony3AI: ; 3a658 (e:6658)
+ cp $20
+ ret nc
+ ld a,5
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUseFullRestore
+
+LoreleiAI: ; 3a664 (e:6664)
+ cp $80
+ ret nc
+ ld a,5
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUseSuperPotion
+
+BrunoAI: ; 3a670 (e:6670)
+ cp $40
+ ret nc
+ jp AIUseXDefend
+
+AgathaAI: ; 3a676 (e:6676)
+ cp $14
+ jp c,AISwitchIfEnoughMons
+ cp $80
+ ret nc
+ ld a,4
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUseSuperPotion
+
+LanceAI: ; 3a687 (e:6687)
+ cp $80
+ ret nc
+ ld a,5
+ call AICheckIfHPBelowFraction
+ ret nc
+ jp AIUseHyperPotion
+
+GenericAI: ; 3a693 (e:6693)
+ and a ; clear carry
+ ret
+
+; end of individual trainer AI routines
+
+DecrementAICount: ; 3a695 (e:6695)
+ ld hl,wAICount
+ dec [hl]
+ scf
+ ret
+
+Func_3a69b: ; 3a69b (e:669b)
+ ld a,(SFX_08_3e - SFX_Headers_08) / 3
+ jp PlaySoundWaitForCurrent
+
+AIUseFullRestore: ; 3a6a0 (e:66a0)
+ call AICureStatus
+ ld a,FULL_RESTORE
+ ld [wcf05],a
+ ld de,wHPBarOldHP
+ ld hl,wEnemyMonHP + 1
+ ld a,[hld]
+ ld [de],a
+ inc de
+ ld a,[hl]
+ ld [de],a
+ inc de
+ ld hl,wEnemyMonMaxHP + 1
+ ld a,[hld]
+ ld [de],a
+ inc de
+ ld [wHPBarMaxHP],a
+ ld [wEnemyMonHP + 1],a
+ ld a,[hl]
+ ld [de],a
+ ld [wHPBarMaxHP+1],a
+ ld [wEnemyMonHP],a
+ jr AIPrintItemUseAndUpdateHPBar
+
+AIUsePotion: ; 3a6ca (e:66ca)
+; enemy trainer heals his monster with a potion
+ ld a,POTION
+ ld b,20
+ jr AIRecoverHP
+
+AIUseSuperPotion: ; 3a6d0 (e:66d0)
+; enemy trainer heals his monster with a super potion
+ ld a,SUPER_POTION
+ ld b,50
+ jr AIRecoverHP
+
+AIUseHyperPotion: ; 3a6d6 (e:66d6)
+; enemy trainer heals his monster with a hyper potion
+ ld a,HYPER_POTION
+ ld b,200
+ ; fallthrough
+
+AIRecoverHP: ; 3a6da (e:66da)
+; heal b HP and print "trainer used $(a) on pokemon!"
+ ld [wcf05],a
+ ld hl,wEnemyMonHP + 1
+ ld a,[hl]
+ ld [wHPBarOldHP],a
+ add b
+ ld [hld],a
+ ld [wHPBarNewHP],a
+ ld a,[hl]
+ ld [wHPBarOldHP+1],a
+ ld [wHPBarNewHP+1],a
+ jr nc,.next
+ inc a
+ ld [hl],a
+ ld [wHPBarNewHP+1],a
+.next
+ inc hl
+ ld a,[hld]
+ ld b,a
+ ld de,wEnemyMonMaxHP + 1
+ ld a,[de]
+ dec de
+ ld [wHPBarMaxHP],a
+ sub b
+ ld a,[hli]
+ ld b,a
+ ld a,[de]
+ ld [wHPBarMaxHP+1],a
+ sbc b
+ jr nc,AIPrintItemUseAndUpdateHPBar
+ inc de
+ ld a,[de]
+ dec de
+ ld [hld],a
+ ld [wHPBarNewHP],a
+ ld a,[de]
+ ld [hl],a
+ ld [wHPBarNewHP+1],a
+ ; fallthrough
+
+AIPrintItemUseAndUpdateHPBar: ; 3a718 (e:6718)
+ call AIPrintItemUse_
+ hlCoord 2, 2
+ xor a
+ ld [wHPBarType],a
+ predef UpdateHPBar2
+ jp DecrementAICount
+
+AISwitchIfEnoughMons: ; 3a72a (e:672a)
+; enemy trainer switches if there are 3 or more unfainted mons in party
+ ld a,[wEnemyPartyCount]
+ ld c,a
+ ld hl,wEnemyMon1HP
+
+ ld d,0 ; keep count of unfainted monsters
+
+ ; count how many monsters haven't fainted yet
+.loop
+ ld a,[hli]
+ ld b,a
+ ld a,[hld]
+ or b
+ jr z,.Fainted ; has monster fainted?
+ inc d
+.Fainted
+ push bc
+ ld bc,$2C
+ add hl,bc
+ pop bc
+ dec c
+ jr nz,.loop
+
+ ld a,d ; how many available monsters are there?
+ cp 2 ; don't bother if only 1 or 2
+ jp nc,SwitchEnemyMon
+ and a
+ ret
+
+SwitchEnemyMon: ; 3a74b (e:674b)
+
+; prepare to withdraw the active monster: copy hp, number, and status to roster
+
+ ld a,[wEnemyMonPartyPos]
+ ld hl,wEnemyMon1HP
+ ld bc,wEnemyMon2 - wEnemyMon1
+ call AddNTimes
+ ld d,h
+ ld e,l
+ ld hl,wEnemyMonHP
+ ld bc,4
+ call CopyData
+
+ ld hl, AIBattleWithdrawText
+ call PrintText
+
+ ld a,1
+ ld [wd11d],a
+ callab EnemySendOut
+ xor a
+ ld [wd11d],a
+
+ ld a,[wLinkState]
+ cp LINK_STATE_BATTLING
+ ret z
+ scf
+ ret
+
+AIBattleWithdrawText: ; 3a781 (e:6781)
+ TX_FAR _AIBattleWithdrawText
+ db "@"
+
+AIUseFullHeal: ; 3a786 (e:6786)
+ call Func_3a69b
+ call AICureStatus
+ ld a,FULL_HEAL
+ jp AIPrintItemUse
+
+AICureStatus: ; 3a791 (e:6791)
+; cures the status of enemy's active pokemon
+ ld a,[wEnemyMonPartyPos]
+ ld hl,wEnemyMon1Status
+ ld bc,wEnemyMon2 - wEnemyMon1
+ call AddNTimes
+ xor a
+ ld [hl],a ; clear status in enemy team roster
+ ld [wEnemyMonStatus],a ; clear status of active enemy
+ ld hl,W_ENEMYBATTSTATUS3
+ res 0,[hl]
+ ret
+
+AIUseXAccuracy: ; 0x3a7a8 unused
+ call Func_3a69b
+ ld hl,W_ENEMYBATTSTATUS2
+ set 0,[hl]
+ ld a,X_ACCURACY
+ jp AIPrintItemUse
+
+AIUseGuardSpec: ; 3a7b5 (e:67b5)
+ call Func_3a69b
+ ld hl,W_ENEMYBATTSTATUS2
+ set 1,[hl]
+ ld a,GUARD_SPEC_
+ jp AIPrintItemUse
+
+AIUseDireHit: ; 0x3a7c2 unused
+ call Func_3a69b
+ ld hl,W_ENEMYBATTSTATUS2
+ set 2,[hl]
+ ld a,DIRE_HIT
+ jp AIPrintItemUse
+
+AICheckIfHPBelowFraction: ; 3a7cf (e:67cf)
+; return carry if enemy trainer's current HP is below 1 / a of the maximum
+ ld [H_DIVISOR],a
+ ld hl,wEnemyMonMaxHP
+ ld a,[hli]
+ ld [H_DIVIDEND],a
+ ld a,[hl]
+ ld [H_DIVIDEND + 1],a
+ ld b,2
+ call Divide
+ ld a,[H_QUOTIENT + 3]
+ ld c,a
+ ld a,[H_QUOTIENT + 2]
+ ld b,a
+ ld hl,wEnemyMonHP + 1
+ ld a,[hld]
+ ld e,a
+ ld a,[hl]
+ ld d,a
+ ld a,d
+ sub b
+ ret nz
+ ld a,e
+ sub c
+ ret
+
+AIUseXAttack: ; 3a7f2 (e:67f2)
+ ld b,$A
+ ld a,X_ATTACK
+ jr AIIncreaseStat
+
+AIUseXDefend: ; 3a7f8 (e:67f8)
+ ld b,$B
+ ld a,X_DEFEND
+ jr AIIncreaseStat
+
+AIUseXSpeed: ; 3a7fe (e:67fe)
+ ld b,$C
+ ld a,X_SPEED
+ jr AIIncreaseStat
+
+AIUseXSpecial: ; 3a804 (e:6804)
+ ld b,$D
+ ld a,X_SPECIAL
+ ; fallthrough
+
+AIIncreaseStat: ; 3a808 (e:6808)
+ ld [wcf05],a
+ push bc
+ call AIPrintItemUse_
+ pop bc
+ ld hl,W_ENEMYMOVEEFFECT
+ ld a,[hld]
+ push af
+ ld a,[hl]
+ push af
+ push hl
+ ld a,$AF
+ ld [hli],a
+ ld [hl],b
+ callab StatModifierUpEffect
+ pop hl
+ pop af
+ ld [hli],a
+ pop af
+ ld [hl],a
+ jp DecrementAICount
+
+AIPrintItemUse: ; 3a82c (e:682c)
+ ld [wcf05],a
+ call AIPrintItemUse_
+ jp DecrementAICount
+
+AIPrintItemUse_: ; 3a835 (e:6835)
+; print "x used [wcf05] on z!"
+ ld a,[wcf05]
+ ld [wd11e],a
+ call GetItemName
+ ld hl, AIBattleUseItemText
+ jp PrintText
+
+AIBattleUseItemText: ; 3a844 (e:6844)
+ TX_FAR _AIBattleUseItemText
+ db "@"
--- /dev/null
+++ b/engine/battle/trainer_pic_money_pointers.asm
@@ -1,0 +1,143 @@
+TrainerPicAndMoneyPointers: ; 39914 (e:5914)
+; trainer pic pointers and base money.
+; money received after battle = base money × level of highest-level enemy mon
+ dw YoungsterPic
+ money 1500
+
+ dw BugCatcherPic
+ money 1000
+
+ dw LassPic
+ money 1500
+
+ dw SailorPic
+ money 3000
+
+ dw JrTrainerMPic
+ money 2000
+
+ dw JrTrainerFPic
+ money 2000
+
+ dw PokemaniacPic
+ money 5000
+
+ dw SuperNerdPic
+ money 2500
+
+ dw HikerPic
+ money 3500
+
+ dw BikerPic
+ money 2000
+
+ dw BurglarPic
+ money 9000
+
+ dw EngineerPic
+ money 5000
+
+ dw JugglerPic
+ money 3500
+
+ dw FisherPic
+ money 3500
+
+ dw SwimmerPic
+ money 500
+
+ dw CueBallPic
+ money 2500
+
+ dw GamblerPic
+ money 7000
+
+ dw BeautyPic
+ money 7000
+
+ dw PsychicPic
+ money 1000
+
+ dw RockerPic
+ money 2500
+
+ dw JugglerPic
+ money 3500
+
+ dw TamerPic
+ money 4000
+
+ dw BirdKeeperPic
+ money 2500
+
+ dw BlackbeltPic
+ money 2500
+
+ dw Rival1Pic
+ money 3500
+
+ dw ProfOakPic
+ money 9900
+
+ dw ChiefPic
+ money 3000
+
+ dw ScientistPic
+ money 5000
+
+ dw GiovanniPic
+ money 9900
+
+ dw RocketPic
+ money 3000
+
+ dw CooltrainerMPic
+ money 3500
+
+ dw CooltrainerFPic
+ money 3500
+
+ dw BrunoPic
+ money 9900
+
+ dw BrockPic
+ money 9900
+
+ dw MistyPic
+ money 9900
+
+ dw LtSurgePic
+ money 9900
+
+ dw ErikaPic
+ money 9900
+
+ dw KogaPic
+ money 9900
+
+ dw BlainePic
+ money 9900
+
+ dw SabrinaPic
+ money 9900
+
+ dw GentlemanPic
+ money 7000
+
+ dw Rival2Pic
+ money 6500
+
+ dw Rival3Pic
+ money 9900
+
+ dw LoreleiPic
+ money 9900
+
+ dw ChannelerPic
+ money 3000
+
+ dw AgathaPic
+ money 9900
+
+ dw LancePic
+ money 9900
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/unused_stats_functions.asm
@@ -1,0 +1,62 @@
+; does nothing since no stats are ever selected (barring glitches)
+DoubleSelectedStats: ; 39680 (e:5680)
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, [wPlayerStatsToDouble]
+ ld hl, wBattleMonAttack + 1
+ jr z, .notEnemyTurn
+ ld a, [wEnemyStatsToDouble]
+ ld hl, wEnemyMonAttack + 1
+.notEnemyTurn
+ ld c, 4
+ ld b, a
+.loop
+ srl b
+ call c, .doubleStat
+ inc hl
+ inc hl
+ dec c
+ ret z
+ jr .loop
+
+.doubleStat
+ ld a, [hl]
+ add a
+ ld [hld], a
+ ld a, [hl]
+ rl a
+ ld [hli], a
+ ret
+
+; does nothing since no stats are ever selected (barring glitches)
+HalveSelectedStats: ; 396a7 (e:56a7)
+ ld a, [H_WHOSETURN]
+ and a
+ ld a, [wPlayerStatsToHalve]
+ ld hl, wBattleMonAttack
+ jr z, .notEnemyTurn
+ ld a, [wEnemyStatsToHalve]
+ ld hl, wEnemyMonAttack
+.notEnemyTurn
+ ld c, 4
+ ld b, a
+.loop
+ srl b
+ call c, .halveStat
+ inc hl
+ inc hl
+ dec c
+ ret z
+ jr .loop
+
+.halveStat
+ ld a, [hl]
+ srl a
+ ld [hli], a
+ rr [hl]
+ or [hl]
+ jr nz, .nonzeroStat
+ ld [hl], 1
+.nonzeroStat
+ dec hl
+ ret
--- /dev/null
+++ b/engine/battle/wild_encounters.asm
@@ -1,0 +1,118 @@
+; try to initiate a wild pokemon encounter
+; returns success in Z
+TryDoWildEncounter: ; 13870 (4:7870)
+ ld a, [wNPCMovementScriptPointerTableNum]
+ and a
+ ret nz
+ ld a, [wd736]
+ and a
+ ret nz
+ callab IsPlayerStandingOnDoorTileOrWarpTile
+ jr nc, .notStandingOnDoorOrWarpTile
+.CantEncounter
+ ld a, $1
+ and a
+ ret
+.notStandingOnDoorOrWarpTile
+ callab IsPlayerJustOutsideMap
+ jr z, .CantEncounter
+ ld a, [wRepelRemainingSteps]
+ and a
+ jr z, .asm_1389e
+ dec a
+ jr z, .lastRepelStep
+ ld [wRepelRemainingSteps], a
+.asm_1389e
+; determine if wild pok�mon can appear in the half-block we�re standing in
+; is the bottom right tile (9,9) of the half-block we're standing in a grass/water tile?
+ hlCoord 9, 9
+ ld c, [hl]
+ ld a, [W_GRASSTILE]
+ cp c
+ ld a, [W_GRASSRATE]
+ jr z, .CanEncounter
+ ld a, $14 ; in all tilesets with a water tile, this is its id
+ cp c
+ ld a, [W_WATERRATE]
+ jr z, .CanEncounter
+; even if not in grass/water, standing anywhere we can encounter pok�mon
+; so long as the map is �indoor� and has wild pok�mon defined.
+; �as long as it�s not Viridian Forest or Safari Zone.
+ ld a, [W_CURMAP]
+ cp REDS_HOUSE_1F ; is this an indoor map?
+ jr c, .CantEncounter2
+ ld a, [W_CURMAPTILESET]
+ cp FOREST ; Viridian Forest/Safari Zone
+ jr z, .CantEncounter2
+ ld a, [W_GRASSRATE]
+.CanEncounter
+; compare encounter chance with a random number to determine if there will be an encounter
+ ld b, a
+ ld a, [hRandomAdd]
+ cp b
+ jr nc, .CantEncounter2
+ ld a, [hRandomSub]
+ ld b, a
+ ld hl, WildMonEncounterSlotChances
+.determineEncounterSlot
+ ld a, [hli]
+ cp b
+ jr nc, .gotEncounterSlot
+ inc hl
+ jr .determineEncounterSlot
+.gotEncounterSlot
+; determine which wild pok�mon (grass or water) can appear in the half-block we�re standing in
+ ld c, [hl]
+ ld hl, W_GRASSMONS
+ aCoord 8, 9
+ cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile?
+ jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default
+ ld hl, W_WATERMONS
+; since the bottom right tile of a "left shore" half-block is $14 but the bottom left tile is not,
+; "left shore" half-blocks (such as the one in the east coast of Cinnabar) load grass encounters.
+.gotWildEncounterType
+ ld b, $0
+ add hl, bc
+ ld a, [hli]
+ ld [W_CURENEMYLVL], a
+ ld a, [hl]
+ ld [wcf91], a
+ ld [wEnemyMonSpecies2], a
+ ld a, [wRepelRemainingSteps]
+ and a
+ jr z, .willEncounter
+ ld a, [wPartyMon1Level]
+ ld b, a
+ ld a, [W_CURENEMYLVL]
+ cp b
+ jr c, .CantEncounter2 ; repel prevents encounters if the leading party mon's level is higher than the wild mon
+ jr .willEncounter
+.lastRepelStep
+ ld [wRepelRemainingSteps], a
+ ld a, $d2
+ ld [H_DOWNARROWBLINKCNT2], a
+ call EnableAutoTextBoxDrawing
+ call DisplayTextID
+.CantEncounter2
+ ld a, $1
+ and a
+ ret
+.willEncounter
+ xor a
+ ret
+
+WildMonEncounterSlotChances: ; 13918 (4:7918)
+; There are 10 slots for wild pokemon, and this is the table that defines how common each of
+; those 10 slots is. A random number is generated and then the first byte of each pair in this
+; table is compared against that random number. If the random number is less than or equal
+; to the first byte, then that slot is chosen. The second byte is double the slot number.
+ db $32, $00 ; 51/256 = 19.9% chance of slot 0
+ db $65, $02 ; 51/256 = 19.9% chance of slot 1
+ db $8C, $04 ; 39/256 = 15.2% chance of slot 2
+ db $A5, $06 ; 25/256 = 9.8% chance of slot 3
+ db $BE, $08 ; 25/256 = 9.8% chance of slot 4
+ db $D7, $0A ; 25/256 = 9.8% chance of slot 5
+ db $E4, $0C ; 13/256 = 5.1% chance of slot 6
+ db $F1, $0E ; 13/256 = 5.1% chance of slot 7
+ db $FC, $10 ; 11/256 = 4.3% chance of slot 8
+ db $FF, $12 ; 3/256 = 1.2% chance of slot 9
--- a/engine/items/items.asm
+++ b/engine/items/items.asm
@@ -320,8 +320,8 @@
ld [W_ANIMATIONID],a
xor a
ld [$fff3],a
- ld [wcc5b],a
- ld [wd05b],a
+ ld [wAnimationType],a
+ ld [wDamageMultipliers],a
ld a,[wWhichPokemon]
push af
ld a,[wcf91]
--- a/engine/menu/status_screen.asm
+++ b/engine/menu/status_screen.asm
@@ -1,3 +1,67 @@
+DrawHP: ; 128ef (4:68ef)
+; Draws the HP bar in the stats screen
+ call GetPredefRegisters
+ ld a, $1
+ jr DrawHP_
+
+DrawHP2: ; 128f6 (4:68f6)
+; Draws the HP bar in the party screen
+ call GetPredefRegisters
+ ld a, $2
+
+DrawHP_: ; 128fb (4:68fb)
+ ld [wHPBarType], a
+ push hl
+ ld a, [wLoadedMonHP]
+ ld b, a
+ ld a, [wLoadedMonHP + 1]
+ ld c, a
+ or b
+ jr nz, .nonzeroHP
+ xor a
+ ld c, a
+ ld e, a
+ ld a, $6
+ ld d, a
+ jp .drawHPBarAndPrintFraction
+.nonzeroHP
+ ld a, [wLoadedMonMaxHP]
+ ld d, a
+ ld a, [wLoadedMonMaxHP + 1]
+ ld e, a
+ predef HPBarLength
+ ld a, $6
+ ld d, a
+ ld c, a
+.drawHPBarAndPrintFraction
+ pop hl
+ push de
+ push hl
+ push hl
+ call DrawHPBar
+ pop hl
+ ld a, [hFlags_0xFFF6]
+ bit 0, a
+ jr z, .printFractionBelowBar
+ ld bc, $9 ; right of bar
+ jr .printFraction
+.printFractionBelowBar
+ ld bc, SCREEN_WIDTH + 1 ; below bar
+.printFraction
+ add hl, bc
+ ld de, wLoadedMonHP
+ ld bc, $203
+ call PrintNumber
+ ld a, "/"
+ ld [hli], a
+ ld de, wLoadedMonMaxHP
+ ld bc, $203
+ call PrintNumber
+ pop hl
+ pop de
+ ret
+
+
; Predef 0x37
StatusScreen: ; 12953 (4:6953)
call LoadMonData
--- /dev/null
+++ b/engine/overworld/is_player_just_outside_map.asm
@@ -1,0 +1,16 @@
+; returns whether the player is one tile outside the map in Z
+IsPlayerJustOutsideMap: ; 128d8 (4:68d8)
+ ld a, [W_YCOORD]
+ ld b, a
+ ld a, [W_CURMAPHEIGHT]
+ call .compareCoordWithMapDimension
+ ret z
+ ld a, [W_XCOORD]
+ ld b, a
+ ld a, [W_CURMAPWIDTH]
+.compareCoordWithMapDimension
+ add a
+ cp b
+ ret z
+ inc b
+ ret
--- a/main.asm
+++ b/main.asm
@@ -1907,7 +1907,7 @@
db $ff ; list terminator
-INCLUDE "engine/battle/1.asm"
+INCLUDE "engine/battle/moveEffects/drain_hp_effect.asm"
INCLUDE "engine/menu/players_pc.asm"
@@ -4755,7 +4755,7 @@
SECTION "Battle (bank 4)", ROMX, BANK[$4]
-INCLUDE "engine/battle/4.asm"
+INCLUDE "engine/overworld/is_player_just_outside_map.asm"
INCLUDE "engine/menu/status_screen.asm"
INCLUDE "engine/menu/party_menu.asm"
@@ -4766,7 +4766,12 @@
INCLUDE "engine/turn_sprite.asm"
INCLUDE "engine/menu/start_sub_menus.asm"
INCLUDE "engine/items/tms.asm"
-INCLUDE "engine/battle/4_2.asm"
+INCLUDE "engine/battle/end_of_battle.asm"
+INCLUDE "engine/battle/wild_encounters.asm"
+INCLUDE "engine/battle/moveEffects/recoil_effect.asm"
+INCLUDE "engine/battle/moveEffects/conversion_effect.asm"
+INCLUDE "engine/battle/moveEffects/haze_effect.asm"
+INCLUDE "engine/battle/get_trainer_name.asm"
INCLUDE "engine/random.asm"
@@ -4820,7 +4825,7 @@
INCLUDE "engine/overworld/map_sprites.asm"
INCLUDE "engine/overworld/emotion_bubbles.asm"
INCLUDE "engine/evolve_trade.asm"
-INCLUDE "engine/battle/5.asm"
+INCLUDE "engine/battle/moveEffects/substitute_effect.asm"
INCLUDE "engine/menu/pc.asm"
@@ -5149,7 +5154,9 @@
SECTION "Battle (bank 9)", ROMX, BANK[$9]
-INCLUDE "engine/battle/9.asm"
+INCLUDE "engine/battle/print_type.asm"
+INCLUDE "engine/battle/save_trainer_name.asm"
+INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm"
SECTION "Pics 2", ROMX, BANK[PICS_2]
@@ -5221,7 +5228,7 @@
SECTION "Battle (bank A)", ROMX, BANK[$A]
-INCLUDE "engine/battle/a.asm"
+INCLUDE "engine/battle/moveEffects/leech_seed_effect.asm"
SECTION "Pics 3", ROMX, BANK[PICS_3]
@@ -5300,7 +5307,7 @@
SECTION "Battle (bank B)", ROMX, BANK[$B]
-INCLUDE "engine/battle/b.asm"
+INCLUDE "engine/battle/display_effectiveness.asm"
TrainerInfoTextBoxTileGraphics: INCBIN "gfx/trainer_info.2bpp"
BlankLeaderNames: INCBIN "gfx/blank_leader_names.2bpp"
@@ -5308,7 +5315,8 @@
BadgeNumbersTileGraphics: INCBIN "gfx/badge_numbers.2bpp"
INCLUDE "engine/items/tmhm.asm"
-INCLUDE "engine/battle/b_2.asm"
+INCLUDE "engine/battle/scale_sprites.asm"
+INCLUDE "engine/battle/moveEffects/pay_day_effect.asm"
INCLUDE "engine/game_corner_slots2.asm"
@@ -5378,7 +5386,8 @@
SECTION "Battle (bank C)", ROMX, BANK[$C]
-INCLUDE "engine/battle/c.asm"
+INCLUDE "engine/battle/moveEffects/mist_effect.asm"
+INCLUDE "engine/battle/moveEffects/one_hit_ko_effect.asm"
SECTION "Pics 5", ROMX, BANK[PICS_5]
@@ -5442,7 +5451,7 @@
SECTION "Battle (bank D)", ROMX, BANK[$D]
INCLUDE "engine/titlescreen2.asm"
-INCLUDE "engine/battle/d.asm"
+INCLUDE "engine/battle/link_battle_versus_text.asm"
INCLUDE "engine/slot_machine.asm"
INCLUDE "engine/overworld/pewter_guys.asm"
INCLUDE "engine/multiply_divide.asm"
@@ -5454,7 +5463,10 @@
INCLUDE "data/moves.asm"
BaseStats: INCLUDE "data/base_stats.asm"
INCLUDE "data/cries.asm"
-INCLUDE "engine/battle/e.asm"
+INCLUDE "engine/battle/unused_stats_functions.asm"
+INCLUDE "engine/battle/scroll_draw_trainer_pic.asm"
+INCLUDE "engine/battle/trainer_ai.asm"
+INCLUDE "engine/battle/draw_hud_pokeball_gfx.asm"
TradingAnimationGraphics:
INCBIN "gfx/game_boy.norepeat.2bpp"
@@ -5465,7 +5477,9 @@
INCBIN "gfx/trade2.2bpp"
INCLUDE "engine/evos_moves.asm"
-INCLUDE "engine/battle/e_2.asm"
+INCLUDE "engine/battle/moveEffects/heal_effect.asm"
+INCLUDE "engine/battle/moveEffects/transform_effect.asm"
+INCLUDE "engine/battle/moveEffects/reflect_light_screen_effect.asm"
SECTION "bankF",ROMX,BANK[$F]
@@ -5938,7 +5952,8 @@
INCLUDE "data/mapObjects/mansion4.asm"
Mansion4Blocks: INCBIN "maps/mansion4.blk"
-INCLUDE "engine/battle/14.asm"
+INCLUDE "engine/battle/init_battle_variables.asm"
+INCLUDE "engine/battle/moveEffects/paralyze_effect.asm"
INCLUDE "engine/overworld/card_key.asm"
@@ -5999,7 +6014,7 @@
FuchsiaHouse3Blocks: INCBIN "maps/fuchsiahouse3.blk"
-INCLUDE "engine/battle/15.asm"
+INCLUDE "engine/battle/experience.asm"
INCLUDE "scripts/route2.asm"
INCLUDE "scripts/route3.asm"
@@ -6079,7 +6094,7 @@
INCBIN "maps/unusedblocks58d7d.blk"
-INCLUDE "engine/battle/16.asm"
+INCLUDE "engine/battle/common_text.asm"
INCLUDE "engine/experience.asm"
@@ -6436,7 +6451,7 @@
SECTION "bank1A",ROMX,BANK[$1A]
-INCLUDE "engine/battle/1a.asm"
+INCLUDE "engine/battle/decrement_pp.asm"
Version_GFX:
IF DEF(_RED)
@@ -6493,7 +6508,8 @@
INCLUDE "engine/hall_of_fame.asm"
INCLUDE "engine/overworld/healing_machine.asm"
INCLUDE "engine/overworld/player_animations.asm"
-INCLUDE "engine/battle/1c.asm"
+INCLUDE "engine/battle/ghost_marowak_anim.asm"
+INCLUDE "engine/battle/battle_transitions.asm"
INCLUDE "engine/town_map.asm"
INCLUDE "engine/mon_party_sprites.asm"
INCLUDE "engine/in_game_trades.asm"
--- a/wram.asm
+++ b/wram.asm
@@ -351,6 +351,10 @@
ds 2
wHallOfFame:: ; cc5b
+wBoostExpByExpAll:: ; cc5b
+wAnimationType:: ; cc5b
+; values between 0-6. Shake screen horizontally, shake screen vertically, blink Pokemon...
+
wcc5b:: ds 1
wcc5c:: ds 1
wcc5d:: ds 1
@@ -377,8 +381,12 @@
wccd3:: ds 1
wccd4:: ds 1
-wccd5:: ds 2
+; if [ccd5] != 1, the second AI layer is not applied
+wAILayer2Encouragement:: ; ccd5
+ ds 1
+ ds 1
+
; current HP of player and enemy substitutes
wPlayerSubstituteHP:: ; ccd7
ds 1
@@ -424,7 +432,7 @@
wcceb:: ds 1
wccec:: ds 1
-wcced:: ds 1
+wMonIsDisobedient:: ds 1
wccee:: ds 1
wccef:: ds 1
wccf0:: ds 1
@@ -431,7 +439,7 @@
wPlayerUsedMove:: ds 1
wEnemyUsedMove:: ds 1
wccf3:: ds 1
-wccf4:: ds 1
+wMoveDidntMiss:: ds 1
wPartyFoughtCurrentEnemyFlags::
; flags that indicate which party members have fought the current enemy mon
@@ -783,7 +791,9 @@
wcf37:: ds 20
wcf4b:: ds 1
wcf4c:: ds 1
-wcf4d:: ds 18
+wGainBoostedExp:: ; cf4d
+ ds 1
+ ds 17
wGymCityName:: ; cf5f
wStringBuffer1:: ; cf5f
@@ -967,7 +977,14 @@
; in safari battle, this is 2
ds 1
-wd05b:: ds 1
+wDamageMultipliers:: ; d05b
+; bits 0-6: Effectiveness
+ ; $0 = immune
+ ; $5 = not very effective
+ ; $a = neutral
+ ; $14 = super-effective
+; bit 7: STAB
+ ds 1
W_LONEATTACKNO:: ; d05c
; which entry in LoneAttacks to use