From a8375aaee71e37fb1e6d39c525dbd40fd0df09bb Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 20:16:31 +0200 Subject: Split commentary lines that are too long --- engine/battle/core.asm | 58 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 21 deletions(-) (limited to 'engine') diff --git a/engine/battle/core.asm b/engine/battle/core.asm index e76a2720..f0f92615 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -454,7 +454,8 @@ MainInBattleLoop: ; 3c233 (f:4233) 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 @@ -1640,7 +1641,8 @@ TryRunningFromBattle: ; 3cab9 (f:4ab9) 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 @@ -2046,8 +2048,10 @@ GetBattleHealthBarColor: ; 3ce90 (f:4e90) 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 @@ DisplayBattleMenu: ; 3ceb3 (f:4eb3) 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 @@ -3155,8 +3160,8 @@ CheckIfPlayerNeedsToChargeUp: ; 3d69a (f:569a) 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 @@ -3307,9 +3312,9 @@ MirrorMoveCheck 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) @@ -3602,7 +3607,8 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) 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,asm_3d714 ; 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 @@ HandleSelfConfusionDamage: ; 3daad (f:5aad) 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 @@ -3914,7 +3921,8 @@ PrintMoveFailureText: ; 3dbe2 (f:5be2) ; 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 @@ -4296,7 +4304,8 @@ GetDamageVarsForPlayerAttack: ; 3ddcf (f:5dcf) 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 @@ GetDamageVarsForEnemyAttack: ; 3de75 (f:5e75) 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] @@ -5025,8 +5035,10 @@ ApplyAttackToPlayerPokemonDone 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,7 +5062,8 @@ AttackSubstitute: ; 3e25e (f:625e) 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 @@ -5536,7 +5549,8 @@ CalcHitChance: ; 3e624 (f:6624) .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 @@ CalcHitChance: ; 3e624 (f:6624) 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 @@ CalcHitChance: ; 3e624 (f:6624) 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] -- cgit v1.2.3 From 247b619e9abf12c6790cff72343a8cf8431b0fb9 Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 20:28:42 +0200 Subject: Some wram constants --- engine/battle/15.asm | 6 +++--- engine/battle/animations.asm | 2 +- engine/battle/b.asm | 2 +- engine/battle/core.asm | 30 +++++++++++++++--------------- engine/items/items.asm | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) (limited to 'engine') diff --git a/engine/battle/15.asm b/engine/battle/15.asm index 0acf3514..9bd67654 100755 --- a/engine/battle/15.asm +++ b/engine/battle/15.asm @@ -82,7 +82,7 @@ GainExperience: ; 5524f (15:524f) call BoostExp ; traded mon exp boost ld a, $1 .next - ld [wcf4d], a + ld [wGainBoostedExp], a ld a, [W_ISINBATTLE] dec a ; is it a trainer battle? call nz, BoostExp ; if so, boost exp @@ -342,12 +342,12 @@ BoostExp: ; 5549f (15:549f) GainedText: ; 554b2 (15:54b2) TX_FAR _GainedText db $08 ; asm - ld a, [wcc5b] + ld a, [wBoostExpByExpAll] ld hl, WithExpAllText and a ret nz ld hl, ExpPointsText - ld a, [wcf4d] + ld a, [wGainBoostedExp] and a ret z ld hl, BoostedText diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index d4cebb44..17033282 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -2931,7 +2931,7 @@ TossBallAnimation: ; 79e16 (1e:5e16) Func_79e6a: ; 79e6a (1e:5e6a) call WaitForSoundToFinish - ld a, [wd05b] + ld a, [wDamageMultipliers] and $7f ret z cp $a diff --git a/engine/battle/b.asm b/engine/battle/b.asm index 32534b17..17f0bd5b 100755 --- a/engine/battle/b.asm +++ b/engine/battle/b.asm @@ -1,5 +1,5 @@ DisplayEffectiveness: ; 2fb7b (b:7b7b) - ld a, [wd05b] + ld a, [wDamageMultipliers] and a, $7F cp a, $0A ret z diff --git a/engine/battle/core.asm b/engine/battle/core.asm index f0f92615..eb4a2fcd 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -919,7 +919,7 @@ FaintEnemyPokemon ; 0x3c567 ; 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 @@ -928,7 +928,7 @@ FaintEnemyPokemon ; 0x3c567 ; 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 @@ -1811,8 +1811,8 @@ SendOutMon: ; 3cc91 (f:4c91) 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 @@ -3129,9 +3129,9 @@ ExecutePlayerMove: ; 3d65e (f:565e) xor a ld [W_MOVEMISSED], a ld [wcced], a - ld [wccf4], a + ld [wMoveDidntMiss], a ld a, $a - ld [wd05b], a + ld [wDamageMultipliers], a ld a, [wcd6a] and a jp nz, ExecutePlayerMoveDone @@ -3277,7 +3277,7 @@ MirrorMoveCheck call PrintCriticalOHKOText callab DisplayEffectiveness ld a,1 - ld [wccf4],a + ld [wMoveDidntMiss],a .notDone ld a,[W_PLAYERMOVEEFFECT] ld hl,AlwaysHappenSideEffects @@ -3901,7 +3901,7 @@ PrintMoveFailureText: ; 3dbe2 (f:5be2) ld de, W_ENEMYMOVEEFFECT .playersTurn ld hl, DoesntAffectMonText - ld a, [wd05b] + ld a, [wDamageMultipliers] and $7f jr z, .gotTextToPrint ld hl, AttackMissedText @@ -5306,7 +5306,7 @@ AdjustDamageForMoveType: ; 3e3a5 (f:63a5) 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] @@ -5329,13 +5329,13 @@ AdjustDamageForMoveType: ; 3e3a5 (f:63a5) 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 @@ -5659,9 +5659,9 @@ ExecuteEnemyMove: ; 3e6bc (f:66bc) 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] @@ -5812,7 +5812,7 @@ asm_3e7ef: ; 3e7ef (f:67ef) call PrintCriticalOHKOText callab DisplayEffectiveness ld a, 1 - ld [wccf4], a + ld [wMoveDidntMiss], a .asm_3e83e ld a, [W_ENEMYMOVEEFFECT] ld hl, AlwaysHappenSideEffects @@ -8614,7 +8614,7 @@ NoEffectText: ; 3fb49 (f:7b49) db "@" Func_3fb4e: ; 3fb4e (f:7b4e) - ld a, [wccf4] + ld a, [wMoveDidntMiss] and a ret nz diff --git a/engine/items/items.asm b/engine/items/items.asm index 605e5dde..3dc17010 100755 --- a/engine/items/items.asm +++ b/engine/items/items.asm @@ -321,7 +321,7 @@ ItemUseBall: ; d687 (3:5687) xor a ld [$fff3],a ld [wcc5b],a - ld [wd05b],a + ld [wDamageMultipliers],a ld a,[wWhichPokemon] push af ld a,[wcf91] -- cgit v1.2.3 From 4ba8dd609065ee118eccdc56a38dc8666b189c2e Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 20:40:22 +0200 Subject: Further document AI stuff --- engine/battle/core.asm | 18 +++++++-------- engine/battle/e.asm | 62 +++++++++++++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 38 deletions(-) (limited to 'engine') diff --git a/engine/battle/core.asm b/engine/battle/core.asm index eb4a2fcd..0f9ee548 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -991,7 +991,7 @@ ReplaceFaintedEnemyMon: ; 3c664 (f:4664) xor a ld [W_ENEMYMOVENUM], a ld [wcd6a], a - ld [wccd5], a + ld [wAILayer2Encouragement], a inc a ; reset Z flag ret @@ -3128,7 +3128,7 @@ ExecutePlayerMove: ; 3d65e (f:565e) jp z, ExecutePlayerMoveDone ; for selected move = FF, skip most of player's turn xor a ld [W_MOVEMISSED], a - ld [wcced], a + ld [wMonIsDisobedient], a ld [wMoveDidntMiss], a ld a, $a ld [wDamageMultipliers], a @@ -3251,7 +3251,7 @@ MirrorMoveCheck 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 @@ -3778,7 +3778,7 @@ MonName1Text: ; 3dafb (f:5afb) ld [hl], a ld [wd11e], a call Func_3db85 - ld a, [wcced] + ld a, [wMonIsDisobedient] and a ld hl, Used2Text ret nz @@ -3799,7 +3799,7 @@ Used2Text: ; 3db34 (f:5b34) db $08 ; asm PrintInsteadText: ; 3db39 (f:5b39) - ld a, [wcced] + ld a, [wMonIsDisobedient] and a jr z, PrintCF4BText ld hl, InsteadText @@ -4007,7 +4007,7 @@ OHKOText: ; 3dc83 (f:5c83) ; 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 @@ -4148,7 +4148,7 @@ CheckForDisobedience: ; 3dc88 (f:5c88) 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] @@ -5655,7 +5655,7 @@ ExecuteEnemyMove: ; 3e6bc (f:66bc) cp $4 ret nc .executeEnemyMove - ld hl, wccd5 + ld hl, wAILayer2Encouragement inc [hl] xor a ld [W_MOVEMISSED], a @@ -5693,7 +5693,7 @@ EnemyCanExecuteChargingMove: ; 3e70b (f:670b) call CopyStringToCF4B EnemyCanExecuteMove: ; 3e72b (f:672b) xor a - ld [wcced], a + ld [wMonIsDisobedient], a call PrintMonName1Text ld a, [W_ENEMYMOVEEFFECT] ld hl, ResidualEffects1 diff --git a/engine/battle/e.asm b/engine/battle/e.asm index d124b77a..feb52df1 100755 --- a/engine/battle/e.asm +++ b/engine/battle/e.asm @@ -227,17 +227,17 @@ AIMoveChoiceModificationFunctionPointers: ; 397a3 (e:57a3) 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 + 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 + ret z ; processed all 4 moves inc hl ld a, [de] and a - ret z ; no more moves in move set + ret z ; no more moves in move set inc de call ReadMove ld a, [W_ENEMYMOVEPOWER] @@ -255,32 +255,34 @@ AIMoveChoiceModification1: ; 397ab (e:57ab) pop hl jr nc, .nextMove ld a, [hl] - add $5 ; discourage move + add $5 ; heavily discourage move ld [hl], a jr .nextMove StatusAilmentMoveEffects ; 57e2 - db $01 ; some sleep effect? + db $01 ; unused sleep effect db SLEEP_EFFECT db POISON_EFFECT db PARALYZE_EFFECT db $FF -; slightly encourage moves with specific effects +; 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, [wccd5] - cp $1 + ld a, [wAILayer2Encouragement] + cp $1 ret nz - ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest) - ld de, wEnemyMonMoves ; enemy moves - ld b, $5 + 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 + ret z ; processed all 4 moves inc hl ld a, [de] and a - ret z ; no more moves in move set + ret z ; no more moves in move set inc de call ReadMove ld a, [W_ENEMYMOVEEFFECT] @@ -294,21 +296,23 @@ AIMoveChoiceModification2: ; 397e7 (e:57e7) jr c, .preferMove jr .nextMove .preferMove - dec [hl] ; slighly encourage this move + dec [hl] ; sligthly encourage this move jr .nextMove -; encourages moves that are effective against the player's mon +; 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 offest) - ld de, wEnemyMonMoves ; enemy moves + 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 + ret z ; processed all 4 moves inc hl ld a, [de] and a - ret z ; no more moves in move set + ret z ; no more moves in move set inc de call ReadMove push hl @@ -322,9 +326,9 @@ AIMoveChoiceModification3: ; 39817 (e:5817) cp $10 jr z, .nextMove jr c, .notEffectiveMove - dec [hl] ; slighly encourage this move + dec [hl] ; sligthly encourage this move jr .nextMove -.notEffectiveMove ; discourages non-effective moves if better moves are available +.notEffectiveMove ; discourages non-effective moves if better moves are available push hl push de push bc @@ -342,17 +346,17 @@ AIMoveChoiceModification3: ; 39817 (e:5817) call ReadMove ld a, [W_ENEMYMOVEEFFECT] cp SUPER_FANG_EFFECT - jr z, .betterMoveFound ; Super Fang is considered to be a better move + 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 + 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 + 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 nz, .betterMoveFound ; damaging moves of a different type are considered to be better moves jr .loopMoves .betterMoveFound ld c, a @@ -363,7 +367,7 @@ AIMoveChoiceModification3: ; 39817 (e:5817) pop hl and a jr z, .nextMove - inc [hl] ; slighly discourage this move + inc [hl] ; sligthly discourage this move jr .nextMove AIMoveChoiceModification4: ; 39883 (e:5883) ret -- cgit v1.2.3 From c73b5d73f477da2c0a916e683562e0941c5ff1eb Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 20:50:49 +0200 Subject: Label some battle related functions --- engine/battle/core.asm | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'engine') diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 0f9ee548..087b0679 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -875,7 +875,7 @@ FaintEnemyPokemon ; 0x3c567 call WaitForSoundToFinish jr .sfxplayed .wild_win - call Func_3c643 + call EndLowHealthAlarm ld a, MUSIC_DEFEATED_WILD_MON call PlayBattleVictoryMusic .sfxplayed @@ -946,7 +946,7 @@ EnemyMonFaintedText: ; 0x3c63e 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 @@ -996,7 +996,7 @@ ReplaceFaintedEnemyMon: ; 3c664 (f:4664) ret TrainerBattleVictory: ; 3c696 (f:4696) - call Func_3c643 + call EndLowHealthAlarm ld b, MUSIC_DEFEATED_GYM_LEADER ld a, [W_GYMLEADERNO] and a @@ -3188,7 +3188,7 @@ PlayerCalcMoveDamage: ; 3d6dc (f:56dc) 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,handleIfMoveMissed call GetDamageVarsForPlayerAttack call CalculateDamage jp z,asm_3d74b ; for moves with 0 BP, skip any further damage calculation and, for now, skip MoveHitTest @@ -3197,7 +3197,7 @@ PlayerCalcMoveDamage: ; 3d6dc (f:56dc) call RandomizeDamage .moveHitTest call MoveHitTest -asm_3d705 +handleIfMoveMissed ld a,[W_MOVEMISSED] and a jr z,asm_3d714 @@ -3573,7 +3573,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) ld [hl],a ld a,BIDE ld [W_PLAYERMOVENUM],a - ld hl,asm_3d705 ; skip damage calculation, DecrementPP and MoveHitTest + ld hl,handleIfMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest jp .returnToHL .ThrashingAboutCheck @@ -4481,7 +4481,7 @@ CalculateDamage: ; 3df65 (f:5f65) ; 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 @@ -4504,7 +4504,7 @@ CalculateDamage: ; 3df65 (f:5f65) ; 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 @@ -4636,7 +4636,7 @@ CalculateDamage: ; 3df65 (f:5f65) and a ret -Func_3e016: ; 3e016 (f:6016) +JumpToOHKOMoveEffect: ; 3e016 (f:6016) call JumpMoveEffect ld a, [W_MOVEMISSED] dec a @@ -5066,7 +5066,7 @@ AttackSubstitute: ; 3e25e (f:625e) ; 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 @@ -7096,14 +7096,14 @@ JumpMoveEffect: ; 3f132 (f:7132) 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 @@ -7111,7 +7111,7 @@ _JumpMoveEffect: ; 3f138 (f:7138) 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 @@ -7376,7 +7376,7 @@ FreezeBurnParalyzeEffect: ; 3f30c (f:730c) ld [wcc5b], 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] @@ -7488,7 +7488,7 @@ CheckDefrost: ; 3f3e2 (f:73e2) ; 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] @@ -7885,7 +7885,7 @@ MoveMissed: ; 3f65a (f:765a) ld a, [de] cp $44 ret nc - jp Func_3fb4e + jp ConditionalPrintButItFailed MonsStatsFellText: ; 3f661 (f:7661) TX_FAR _MonsStatsFellText @@ -8084,7 +8084,7 @@ SwitchAndTeleportEffect: ; 3f739 (f:7739) ld a, [W_ENEMYMOVENUM] cp TELEPORT jp nz, PrintText - jp Func_3fb4e + jp ConditionalPrintButItFailed .asm_3f7e4 push af call PlayBattleAnimation @@ -8358,7 +8358,7 @@ ConfusionEffectFailed: ; 3f9a6 (f:79a6) ret z ld c, $32 call DelayFrames - jp Func_3fb4e + jp ConditionalPrintButItFailed ParalyzeEffect: ; 3f9b1 (f:79b1) ld hl, ParalyzeEffect_ @@ -8613,10 +8613,10 @@ NoEffectText: ; 3fb49 (f:7b49) TX_FAR _NoEffectText db "@" -Func_3fb4e: ; 3fb4e (f:7b4e) +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 -- cgit v1.2.3 From e6185ac358b2e548536485781d6ec584c0b7742d Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 21:09:43 +0200 Subject: Label some attack animation functions --- engine/battle/animations.asm | 14 +++++---- engine/battle/core.asm | 73 ++++++++++++++++++++++---------------------- engine/items/items.asm | 2 +- 3 files changed, 46 insertions(+), 43 deletions(-) (limited to 'engine') diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index 17033282..1ed3a725 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -446,7 +446,7 @@ ShareMoveAnimations: ; 78da6 (1e:4da6) ret Func_78dbd: ; 78dbd (1e:4dbd) - ld a,[wcc5b] + ld a,[wAnimationType] and a ret z dec a @@ -469,12 +469,12 @@ PointerTable_78dcf: ; 78dcf (1e:4dcf) dw Func_78dfe Func_78ddb: ; 78ddb (1e:4ddb) - call Func_79e6a + call PlayApplyingAttackSound ld b, $8 jp Func_79209 Func_78de3: ; 78de3 (1e:4de3) - call Func_79e6a + call PlayApplyingAttackSound ld b, $8 jp Func_79210 @@ -483,11 +483,11 @@ Func_78deb: ; 78deb (1e:4deb) jr Func_78e01 Func_78df0: ; 78df0 (1e:4df0) - call Func_79e6a + call PlayApplyingAttackSound jp AnimationBlinkEnemyMon Func_78df6: ; 78df6 (1e:4df6) - call Func_79e6a + call PlayApplyingAttackSound ld b, $2 jp Func_79210 @@ -2929,7 +2929,9 @@ TossBallAnimation: ; 79e16 (1e:5e16) 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, [wDamageMultipliers] and $7f diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 087b0679..678ade24 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -582,7 +582,7 @@ HandlePoisonBurnLeechSeed: ; 3c3bd (f:43bd) .poisoned call PrintText xor a - ld [wcc5b], a + ld [wAnimationType], a ld a,BURN_PSN_ANIM call PlayMoveAnimation ; play burn/poison animation pop hl @@ -603,7 +603,7 @@ HandlePoisonBurnLeechSeed: ; 3c3bd (f:43bd) 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 @@ -3219,7 +3219,7 @@ asm_3d71e ld b,BANK(Func_79747) call nz,Bankswitch pop af - ld [wcc5b],a + ld [wAnimationType],a ld a,[W_PLAYERMOVENUM] call PlayMoveAnimation call HandleExplodingAnimation @@ -3241,7 +3241,7 @@ asm_3d74b jr MirrorMoveCheck .playAnim xor a - ld [wcc5b],a + ld [wAnimationType],a ld a,STATUS_AFFECTED_ANIM call PlayMoveAnimation MirrorMoveCheck @@ -3386,7 +3386,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) 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 @@ -3470,7 +3470,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) ld hl,IsConfusedText call PrintText xor a - ld [wcc5b],a + ld [wAnimationType],a ld a,CONF_ANIM - 1 call PlayMoveAnimation call BattleRandom @@ -3519,7 +3519,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) .FlyOrChargeEffect xor a - ld [wcc5b],a + ld [wAnimationType],a ld a,STATUS_AFFECTED_ANIM call PlayMoveAnimation .NotFlyOrChargeEffect @@ -3751,7 +3751,7 @@ HandleSelfConfusionDamage: ; 3daad (f:5aad) pop af ld [hl], a xor a - ld [wcc5b], a + ld [wAnimationType], a inc a ld [H_WHOSETURN], a call PlayMoveAnimation @@ -5198,7 +5198,7 @@ ReloadMoveData: ; 3e329 (f:6329) ; 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 @@ -5754,7 +5754,7 @@ asm_3e7a4: ; 3e7a4 (f:67a4) ld b, BANK(Func_79747) call nz, Bankswitch pop af - ld [wcc5b], a + ld [wAnimationType], a ld a, [W_ENEMYMOVENUM] call PlayMoveAnimation call HandleExplodingAnimation @@ -5778,7 +5778,7 @@ Func_3e7d1: ; 3e7d1 (f:67d1) jr asm_3e7ef .asm_3e7e6 xor a - ld [wcc5b], a + ld [wAnimationType], a ld a,STATUS_AFFECTED_ANIM call PlayMoveAnimation asm_3e7ef: ; 3e7ef (f:67ef) @@ -5870,7 +5870,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f) ld hl, FastAsleepText call PrintText xor a - ld [wcc5b], a + ld [wAnimationType], a ld a,SLP_ANIM call PlayMoveAnimation jr .next1 @@ -5946,7 +5946,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f) ld hl, IsConfusedText call PrintText xor a - ld [wcc5b], a + ld [wAnimationType], a ld a,CONF_ANIM call PlayMoveAnimation call BattleRandom @@ -5989,7 +5989,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f) pop af ld [hl], a xor a - ld [wcc5b], a + ld [wAnimationType], a ld [H_WHOSETURN], a ld a, POUND call PlayMoveAnimation @@ -6030,7 +6030,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f) jr .notFlyOrChargeEffect .flyOrChargeEffect xor a - ld [wcc5b], a + ld [wAnimationType], a ld a, STATUS_AFFECTED_ANIM call PlayMoveAnimation .notFlyOrChargeEffect @@ -6803,7 +6803,7 @@ HandleExplodingAnimation: ; 3eed3 (f:6ed3) and a ret nz ld a, 5 - ld [wcc5b], a + ld [wAnimationType], a PlayMoveAnimation: ; 3ef07 (f:6f07) ld [W_ANIMATIONID],a @@ -7239,7 +7239,7 @@ SleepEffect: ; 3f1fc (f:71fc) and $7 jr z, .setSleepCounter ld [de], a - call Func_3fb89 + call StoreCurrentMoveAnimationIDAndType ld hl, FellAsleepText jp PrintText .didntAffect @@ -7325,10 +7325,10 @@ PoisonEffect: ; 3f24f (f:724f) cp POISON_EFFECT jr z, .asm_3f2cd ld a, b - call Func_3fb96 + call StoreAnimationIDAndType jp PrintText .asm_3f2cd - call Func_3fb89 + call StoreCurrentMoveAnimationIDAndType jp PrintText .noEffect ld a, [de] @@ -7373,7 +7373,7 @@ ExplodeEffect: ; 3f2f1 (f:72f1) 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, [H_WHOSETURN] @@ -7854,7 +7854,7 @@ UpdateLoweredStatDone: ; 3f62c (f:762c) ld a, [de] cp $44 jr nc, .ApplyBadgeBoostsAndStatusPenalties - call Func_3fb89 + call StoreCurrentMoveAnimationIDAndType .ApplyBadgeBoostsAndStatusPenalties ld a, [H_WHOSETURN] and a @@ -7977,7 +7977,7 @@ BideEffect: ; 3f6e5 (f:76e5) ld [bc], a ; set Bide counter to 2 or 3 at random ld a, [H_WHOSETURN] add XSTATITEM_ANIM - jp Func_3fb96 + jp StoreAnimationIDAndType ThrashPetalDanceEffect: ; 3f717 (f:7717) ld hl, W_PLAYERBATTSTATUS1 @@ -7996,7 +7996,7 @@ ThrashPetalDanceEffect: ; 3f717 (f:7717) 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 StoreAnimationIDAndType SwitchAndTeleportEffect: ; 3f739 (f:7739) ld a, [H_WHOSETURN] @@ -8030,7 +8030,7 @@ SwitchAndTeleportEffect: ; 3f739 (f:7739) .asm_3f76e call ReadPlayerMonCurHPAndStatus xor a - ld [wcc5b], a + ld [wAnimationType], a inc a ld [wEscapedFromBattle], a ld a, [W_PLAYERMOVENUM] @@ -8072,7 +8072,7 @@ SwitchAndTeleportEffect: ; 3f739 (f:7739) .asm_3f7c1 call ReadPlayerMonCurHPAndStatus xor a - ld [wcc5b], a + ld [wAnimationType], a inc a ld [wEscapedFromBattle], a ld a, [W_ENEMYMOVENUM] @@ -8213,7 +8213,7 @@ ChargeEffect: ; 3f88c (f:788c) ld b, ANIM_C0 .notDigOrFly xor a - ld [wcc5b], a + ld [wAnimationType], a ld a, b call PlayBattleAnimation ld a, [de] @@ -8345,7 +8345,7 @@ ConfusionSideEffectSuccess: ; 3f96f (f:796f) ld [bc], a ; confusion status will last 2-5 turns pop af cp CONFUSION_SIDE_EFFECT - call nz, Func_3fb89 + call nz, StoreCurrentMoveAnimationIDAndType ld hl, BecameConfusedText jp PrintText @@ -8550,7 +8550,7 @@ DisableEffect: ; 3fa8a (f:7a8a) swap c add c ld [de], a - call Func_3fb89 + call StoreCurrentMoveAnimationIDAndType ld hl, wccee ld a, [H_WHOSETURN] and a @@ -8658,7 +8658,8 @@ CheckTargetSubstitute: ; 3fb79 (f:7b79) pop hl ret -Func_3fb89: ; 3fb89 (f:7b89) +StoreCurrentMoveAnimationIDAndType: ; 3fb89 (f:7b89) +; animation at MOVENUM will be played unless MOVENUM is 0 ld a, [H_WHOSETURN] and a ld a, [W_PLAYERMOVENUM] @@ -8668,20 +8669,20 @@ Func_3fb89: ; 3fb89 (f:7b89) and a ret z -Func_3fb96: ; 3fb96 (f:7b96) +StoreAnimationIDAndType: ; 3fb96 (f:7b96) 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) xor a - ld [wcc5b], a + ld [wAnimationType], a ld a, [H_WHOSETURN] and a ld a, [W_PLAYERMOVENUM] @@ -8694,7 +8695,7 @@ PlayCurrentMoveAnimation: ; 3fba8 (f:7ba8) PlayBattleAnimation: ; 3fbb9 (f:7bb9) ld [W_ANIMATIONID], a -Func_3fbbc: ; 3fbbc (f:7bbc) +PlayBattleAnimationGotID: ; 3fbbc (f:7bbc) push hl push de push bc diff --git a/engine/items/items.asm b/engine/items/items.asm index 3dc17010..21e6e924 100755 --- a/engine/items/items.asm +++ b/engine/items/items.asm @@ -320,7 +320,7 @@ ItemUseBall: ; d687 (3:5687) ld [W_ANIMATIONID],a xor a ld [$fff3],a - ld [wcc5b],a + ld [wAnimationType],a ld [wDamageMultipliers],a ld a,[wWhichPokemon] push af -- cgit v1.2.3 From 4e2084b0f167a9e5c8d0cde93cc81833fec9056c Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 22:22:12 +0200 Subject: Name more in-battle functions and labels and better document some animation related functions --- engine/battle/core.asm | 115 ++++++++++++++++++++++++++----------------------- engine/battle/e.asm | 4 +- 2 files changed, 64 insertions(+), 55 deletions(-) (limited to 'engine') diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 678ade24..bad8f831 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -3188,30 +3188,30 @@ PlayerCalcMoveDamage: ; 3d6dc (f:56dc) jp c,.moveHitTest ; SetDamageEffects moves (e.g. Seismic Toss and Super Fang) skip damage calculation call CriticalHitTest call HandleCounterMove - jr z,handleIfMoveMissed + 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 -handleIfMoveMissed +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 @@ -3230,7 +3230,7 @@ asm_3d71e ld b,BANK(Func_79771) call nz,Bankswitch jr MirrorMoveCheck -asm_3d74b +playerCheckIfFlyOrChargeEffect ld c,$1E call DelayFrames ld a,[W_PLAYERMOVEEFFECT] @@ -3297,8 +3297,8 @@ MirrorMoveCheck 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 @@ -3573,7 +3573,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) ld [hl],a ld a,BIDE ld [W_PLAYERMOVENUM],a - ld hl,handleIfMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest + ld hl,handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest jp .returnToHL .ThrashingAboutCheck @@ -3607,7 +3607,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854) 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), + ld hl,getPlayerAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit), ; DecrementPP and MoveHitTest jp nz,.returnToHL jp .returnToHL @@ -3783,7 +3783,7 @@ MonName1Text: ; 3dafb (f:5afb) ld hl, Used2Text ret nz ld a, [wd11e] - cp DOUBLESLAP + cp 3 ld hl, Used2Text ret c ld hl, Used1Text @@ -3922,7 +3922,7 @@ PrintMoveFailureText: ; 3dbe2 (f:5be2) ; 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. + ; even if it was intended to be potential damage/8. ld a, [hli] ld b, [hl] srl a @@ -5639,6 +5639,7 @@ RandomizeDamage: ; 3e687 (f:6687) ld [hl], a ret +; for more detailed commentary, see equivalent function for player side (ExecutePlayerMove) ExecuteEnemyMove: ; 3e6bc (f:66bc) ld a, [wEnemySelectedMove] inc a @@ -5711,42 +5712,42 @@ EnemyCalcMoveDamage: ; 3e750 (f:6750) 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 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? @@ -5764,24 +5765,24 @@ asm_3e7a4: ; 3e7a4 (f:67a4) 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 [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 @@ -5832,7 +5833,7 @@ asm_3e7ef: ; 3e7ef (f:67ef) 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 @@ -6084,7 +6085,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f) 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? @@ -6115,7 +6116,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f) call PrintText ld hl, wEnemyNumAttacksLeft dec [hl] - ld hl, Func_3e794 + ld hl, GetEnemyAnimationType jp nz, .enemyReturnToHL jp .enemyReturnToHL .checkIfUsingRage @@ -6971,6 +6972,7 @@ _LoadTrainerPic: ; 3f04b (f:704b) ld c, a jp LoadUncompressedSpriteData +; unreferenced Func_3f069: ; 3f069 (f:7069) xor a ld [wc0f1], a @@ -7046,6 +7048,7 @@ asm_3f0d0: ; 3f0d0 (f:70d0) dec b jr nz, .asm_3f0de ret + .asm_3f0ed push bc ld b, $0 @@ -7069,7 +7072,7 @@ asm_3f0d0: ; 3f0d0 (f:70d0) jr nz, .asm_3f0f4 ret -LoadMonBackPic: +LoadMonBackPic: ; 3f103 (f:7103) ; Assumes the monster's attributes have ; been loaded with GetMonHeader. ld a, [wBattleMonSpecies2] @@ -7239,7 +7242,7 @@ SleepEffect: ; 3f1fc (f:71fc) and $7 jr z, .setSleepCounter ld [de], a - call StoreCurrentMoveAnimationIDAndType + call PlayCurrentMoveAnimation2 ld hl, FellAsleepText jp PrintText .didntAffect @@ -7325,10 +7328,10 @@ PoisonEffect: ; 3f24f (f:724f) cp POISON_EFFECT jr z, .asm_3f2cd ld a, b - call StoreAnimationIDAndType + call PlayBattleAnimation2 jp PrintText .asm_3f2cd - call StoreCurrentMoveAnimationIDAndType + call PlayCurrentMoveAnimation2 jp PrintText .noEffect ld a, [de] @@ -7584,7 +7587,7 @@ StatModifierUpEffect: ; 3f428 (f:7428) 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 @@ -7677,7 +7680,7 @@ UpdateStatDone: ; 3f4ca (f:74ca) 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] @@ -7854,7 +7857,7 @@ UpdateLoweredStatDone: ; 3f62c (f:762c) ld a, [de] cp $44 jr nc, .ApplyBadgeBoostsAndStatusPenalties - call StoreCurrentMoveAnimationIDAndType + call PlayCurrentMoveAnimation2 .ApplyBadgeBoostsAndStatusPenalties ld a, [H_WHOSETURN] and a @@ -7977,7 +7980,7 @@ BideEffect: ; 3f6e5 (f:76e5) ld [bc], a ; set Bide counter to 2 or 3 at random ld a, [H_WHOSETURN] add XSTATITEM_ANIM - jp StoreAnimationIDAndType + jp PlayBattleAnimation2 ThrashPetalDanceEffect: ; 3f717 (f:7717) ld hl, W_PLAYERBATTSTATUS1 @@ -7996,7 +7999,7 @@ ThrashPetalDanceEffect: ; 3f717 (f:7717) ld [de], a ; set thrash/petal dance counter to 2 or 3 at random ld a, [H_WHOSETURN] add ANIM_B0 - jp StoreAnimationIDAndType + jp PlayBattleAnimation2 SwitchAndTeleportEffect: ; 3f739 (f:7739) ld a, [H_WHOSETURN] @@ -8345,7 +8348,7 @@ ConfusionSideEffectSuccess: ; 3f96f (f:796f) ld [bc], a ; confusion status will last 2-5 turns pop af cp CONFUSION_SIDE_EFFECT - call nz, StoreCurrentMoveAnimationIDAndType + call nz, PlayCurrentMoveAnimation2 ld hl, BecameConfusedText jp PrintText @@ -8550,7 +8553,7 @@ DisableEffect: ; 3fa8a (f:7a8a) swap c add c ld [de], a - call StoreCurrentMoveAnimationIDAndType + call PlayCurrentMoveAnimation2 ld hl, wccee ld a, [H_WHOSETURN] and a @@ -8658,18 +8661,20 @@ CheckTargetSubstitute: ; 3fb79 (f:7b79) pop hl ret -StoreCurrentMoveAnimationIDAndType: ; 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 -StoreAnimationIDAndType: ; 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 @@ -8681,6 +8686,8 @@ StoreAnimationIDAndType: ; 3fb96 (f:7b96) jp PlayBattleAnimationGotID PlayCurrentMoveAnimation: ; 3fba8 (f:7ba8) +; animation at MOVENUM will be played unless MOVENUM is 0 +; resets wAnimationType xor a ld [wAnimationType], a ld a, [H_WHOSETURN] @@ -8693,9 +8700,11 @@ PlayCurrentMoveAnimation: ; 3fba8 (f:7ba8) ret z PlayBattleAnimation: ; 3fbb9 (f:7bb9) +; play animation ID at a and predefined animation type ld [W_ANIMATIONID], a PlayBattleAnimationGotID: ; 3fbbc (f:7bbc) +; play animation at W_ANIMATIONID push hl push de push bc diff --git a/engine/battle/e.asm b/engine/battle/e.asm index feb52df1..e7802e4e 100755 --- a/engine/battle/e.asm +++ b/engine/battle/e.asm @@ -273,7 +273,7 @@ AIMoveChoiceModification2: ; 397e7 (e:57e7) ld a, [wAILayer2Encouragement] cp $1 ret nz - ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest) + ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset) ld de, wEnemyMonMoves ; enemy moves ld b, NUM_MOVES + 1 .nextMove @@ -303,7 +303,7 @@ AIMoveChoiceModification2: ; 397e7 (e:57e7) ; 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 offest) + ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset) ld de, wEnemyMonMoves ; enemy moves ld b, $5 .nextMove -- cgit v1.2.3 From 9d93b5b630eaabd57f213c9dc5761223ff7445ec Mon Sep 17 00:00:00 2001 From: xCrystal Date: Tue, 31 Mar 2015 23:45:57 +0200 Subject: Document animation types (shake screen/blink pic) --- engine/battle/animations.asm | 50 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'engine') diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index 1ed3a725..0f12e05a 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -407,7 +407,7 @@ MoveAnimation: ; 78d5e (1e:4d5e) ld c,30 call DelayFrames .next4 - call Func_78dbd ; reload pic and flash the pic in and out (to show damage) + call PlayApplyingAttackAnimation ; reload pic and flash the pic in and out (to show damage) .AnimationFinished call WaitForSoundToFinish xor a @@ -445,7 +445,9 @@ ShareMoveAnimations: ; 78da6 (1e:4da6) ld [W_ANIMATIONID],a ret -Func_78dbd: ; 78dbd (1e:4dbd) +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 @@ -453,48 +455,48 @@ Func_78dbd: ; 78dbd (1e:4dbd) add a ld c,a ld b,0 - ld hl,PointerTable_78dcf + ld hl,AnimationTypePointerTable add hl,bc ld a,[hli] ld h,[hl] 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 non-damaging move + dw ShakeScreenHorizontallyHeavy ; enemy mon has used a damaging move with a side effect + dw ShakeScreenHorizontallySlow ; enemy mon has used a damaging move without a side effect + dw BlinkEnemyMonSprite ; player mon has used a non-damaging move + dw ShakeScreenHorizontallyLight ; player mon has used a damaging move with a side effect + dw ShakeScreenHorizontallySlow2 ; player mon has used a damaging move without a side effect -Func_78ddb: ; 78ddb (1e:4ddb) +ShakeScreenVertically: ; 78ddb (1e:4ddb) call PlayApplyingAttackSound ld b, $8 - jp Func_79209 + jp AnimationShakeScreenVertically -Func_78de3: ; 78de3 (1e:4de3) +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) +BlinkEnemyMonSprite: ; 78df0 (1e:4df0) call PlayApplyingAttackSound jp AnimationBlinkEnemyMon -Func_78df6: ; 78df6 (1e:4df6) +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 @@ Func_78e01: ; 78e01 (1e:4e01) jr nz, .asm_78e11 pop bc dec c - jr nz, Func_78e01 + jr nz, AnimationShakeScreenHorizontallySlow ret Func_78e23: ; 78e23 (1e:4e23) @@ -1225,14 +1227,14 @@ Func_791fc: ; 791fc (1e:51fc) ld b, $5 -Func_79209: ; 79209 (1e:5209) +AnimationShakeScreenVertically: ; 79209 (1e:5209) predef_jump Func_480ff AnimationShakeScreen: ; 7920e (1e:520e) ; 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) -- cgit v1.2.3 From e74dce24b4bbb0d0d23a1724932b289050b66d4a Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 11:23:27 +0200 Subject: Rename battle files and split move effects Part 1 1.asm, 4.asm, and 4_2.asm --- engine/battle/1.asm | 104 ------ engine/battle/4.asm | 77 ----- engine/battle/4_2.asm | 413 ------------------------ engine/battle/animations.asm | 26 +- engine/battle/e.asm | 2 +- engine/battle/end_of_battle.asm | 88 +++++ engine/battle/get_trainer_name.asm | 24 ++ engine/battle/moveEffects/conversion_effect.asm | 34 ++ engine/battle/moveEffects/drain_hp_effect.asm | 104 ++++++ engine/battle/moveEffects/haze_effect.asm | 76 +++++ engine/battle/moveEffects/recoil_effect.asm | 68 ++++ engine/battle/wild_encounters.asm | 118 +++++++ engine/menu/status_screen.asm | 64 ++++ engine/overworld/is_player_just_outside_map.asm | 16 + 14 files changed, 606 insertions(+), 608 deletions(-) delete mode 100755 engine/battle/1.asm delete mode 100755 engine/battle/4.asm delete mode 100755 engine/battle/4_2.asm create mode 100644 engine/battle/end_of_battle.asm create mode 100644 engine/battle/get_trainer_name.asm create mode 100644 engine/battle/moveEffects/conversion_effect.asm create mode 100644 engine/battle/moveEffects/drain_hp_effect.asm create mode 100644 engine/battle/moveEffects/haze_effect.asm create mode 100644 engine/battle/moveEffects/recoil_effect.asm create mode 100644 engine/battle/wild_encounters.asm create mode 100644 engine/overworld/is_player_just_outside_map.asm (limited to 'engine') diff --git a/engine/battle/1.asm b/engine/battle/1.asm deleted file mode 100755 index 517d53d1..00000000 --- a/engine/battle/1.asm +++ /dev/null @@ -1,104 +0,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 "@" diff --git a/engine/battle/4.asm b/engine/battle/4.asm deleted file mode 100755 index e96267c4..00000000 --- a/engine/battle/4.asm +++ /dev/null @@ -1,77 +0,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 diff --git a/engine/battle/4_2.asm b/engine/battle/4_2.asm deleted file mode 100755 index ea29cca7..00000000 --- a/engine/battle/4_2.asm +++ /dev/null @@ -1,413 +0,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 diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index 0f12e05a..dc08e0e1 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -407,7 +407,7 @@ MoveAnimation: ; 78d5e (1e:4d5e) ld c,30 call DelayFrames .next4 - call PlayApplyingAttackAnimation ; 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 @@ -463,37 +463,37 @@ PlayApplyingAttackAnimation: ; 78dbd (1e:4dbd) jp [hl] AnimationTypePointerTable: ; 78dcf (1e:4dcf) - dw ShakeScreenVertically ; enemy mon has used a non-damaging move + 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 damaging move without a side effect - dw BlinkEnemyMonSprite ; player mon has used a non-damaging move + 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 damaging move without a side effect + dw ShakeScreenHorizontallySlow2 ; player mon has used a non-damaging move -ShakeScreenVertically: ; 78ddb (1e:4ddb) +ShakeScreenVertically: ; 78ddb (1e:4ddb) call PlayApplyingAttackSound ld b, $8 jp AnimationShakeScreenVertically -ShakeScreenHorizontallyHeavy: ; 78de3 (1e:4de3) +ShakeScreenHorizontallyHeavy: ; 78de3 (1e:4de3) call PlayApplyingAttackSound ld b, $8 - jp AnimationShakeScreenHorizontallyFast + jp AnimationShakeScreenHorizontallyFast -ShakeScreenHorizontallySlow: ; 78deb (1e:4deb) +ShakeScreenHorizontallySlow: ; 78deb (1e:4deb) ld bc, $602 - jr AnimationShakeScreenHorizontallySlow + jr AnimationShakeScreenHorizontallySlow -BlinkEnemyMonSprite: ; 78df0 (1e:4df0) +BlinkEnemyMonSprite: ; 78df0 (1e:4df0) call PlayApplyingAttackSound jp AnimationBlinkEnemyMon -ShakeScreenHorizontallyLight: ; 78df6 (1e:4df6) +ShakeScreenHorizontallyLight: ; 78df6 (1e:4df6) call PlayApplyingAttackSound ld b, $2 jp AnimationShakeScreenHorizontallyFast -ShakeScreenHorizontallySlow2: ; 78dfe (1e:4dfe) +ShakeScreenHorizontallySlow2: ; 78dfe (1e:4dfe) ld bc, $302 AnimationShakeScreenHorizontallySlow: ; 78e01 (1e:4e01) diff --git a/engine/battle/e.asm b/engine/battle/e.asm index e7802e4e..1144abe8 100755 --- a/engine/battle/e.asm +++ b/engine/battle/e.asm @@ -335,7 +335,7 @@ AIMoveChoiceModification3: ; 39817 (e:5817) ld a, [W_ENEMYMOVETYPE] ld d, a ld hl, wEnemyMonMoves ; enemy moves - ld b, $5 + ld b, NUM_MOVES + 1 ld c, $0 .loopMoves dec b diff --git a/engine/battle/end_of_battle.asm b/engine/battle/end_of_battle.asm new file mode 100644 index 00000000..f03dd07f --- /dev/null +++ b/engine/battle/end_of_battle.asm @@ -0,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 diff --git a/engine/battle/get_trainer_name.asm b/engine/battle/get_trainer_name.asm new file mode 100644 index 00000000..961f25cf --- /dev/null +++ b/engine/battle/get_trainer_name.asm @@ -0,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 diff --git a/engine/battle/moveEffects/conversion_effect.asm b/engine/battle/moveEffects/conversion_effect.asm new file mode 100644 index 00000000..511df2fd --- /dev/null +++ b/engine/battle/moveEffects/conversion_effect.asm @@ -0,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 diff --git a/engine/battle/moveEffects/drain_hp_effect.asm b/engine/battle/moveEffects/drain_hp_effect.asm new file mode 100644 index 00000000..517d53d1 --- /dev/null +++ b/engine/battle/moveEffects/drain_hp_effect.asm @@ -0,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 "@" diff --git a/engine/battle/moveEffects/haze_effect.asm b/engine/battle/moveEffects/haze_effect.asm new file mode 100644 index 00000000..2343e784 --- /dev/null +++ b/engine/battle/moveEffects/haze_effect.asm @@ -0,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 "@" diff --git a/engine/battle/moveEffects/recoil_effect.asm b/engine/battle/moveEffects/recoil_effect.asm new file mode 100644 index 00000000..0460b208 --- /dev/null +++ b/engine/battle/moveEffects/recoil_effect.asm @@ -0,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 "@" diff --git a/engine/battle/wild_encounters.asm b/engine/battle/wild_encounters.asm new file mode 100644 index 00000000..03119b90 --- /dev/null +++ b/engine/battle/wild_encounters.asm @@ -0,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 diff --git a/engine/menu/status_screen.asm b/engine/menu/status_screen.asm index f95a0710..b5254694 100755 --- 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 diff --git a/engine/overworld/is_player_just_outside_map.asm b/engine/overworld/is_player_just_outside_map.asm new file mode 100644 index 00000000..24e434b3 --- /dev/null +++ b/engine/overworld/is_player_just_outside_map.asm @@ -0,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 -- cgit v1.2.3 From 46c2a38c7c55ff01e8787dfd624cb1c771248b6c Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 11:41:20 +0200 Subject: Rename battle files and split move effects Part 2 5.asm, 9.asm, and a.asm --- engine/battle/5.asm | 77 --------- engine/battle/9.asm | 190 ---------------------- engine/battle/a.asm | 39 ----- engine/battle/core.asm | 4 +- engine/battle/moveEffects/focus_energy_effect.asm | 24 +++ engine/battle/moveEffects/leech_seed_effect.asm | 39 +++++ engine/battle/moveEffects/substitute_effect.asm | 77 +++++++++ engine/battle/print_type.asm | 52 ++++++ engine/battle/save_trainer_name.asm | 112 +++++++++++++ 9 files changed, 306 insertions(+), 308 deletions(-) delete mode 100755 engine/battle/5.asm delete mode 100755 engine/battle/9.asm delete mode 100755 engine/battle/a.asm create mode 100644 engine/battle/moveEffects/focus_energy_effect.asm create mode 100644 engine/battle/moveEffects/leech_seed_effect.asm create mode 100644 engine/battle/moveEffects/substitute_effect.asm create mode 100644 engine/battle/print_type.asm create mode 100644 engine/battle/save_trainer_name.asm (limited to 'engine') diff --git a/engine/battle/5.asm b/engine/battle/5.asm deleted file mode 100755 index ef3e1362..00000000 --- a/engine/battle/5.asm +++ /dev/null @@ -1,77 +0,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 "@" diff --git a/engine/battle/9.asm b/engine/battle/9.asm deleted file mode 100755 index e7265f41..00000000 --- a/engine/battle/9.asm +++ /dev/null @@ -1,190 +0,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 "@" diff --git a/engine/battle/a.asm b/engine/battle/a.asm deleted file mode 100755 index a257d143..00000000 --- a/engine/battle/a.asm +++ /dev/null @@ -1,39 +0,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 "@" diff --git a/engine/battle/core.asm b/engine/battle/core.asm index bad8f831..48bed512 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -8369,8 +8369,8 @@ ParalyzeEffect: ; 3f9b1 (f:79b1) 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) diff --git a/engine/battle/moveEffects/focus_energy_effect.asm b/engine/battle/moveEffects/focus_energy_effect.asm new file mode 100644 index 00000000..f01e61cc --- /dev/null +++ b/engine/battle/moveEffects/focus_energy_effect.asm @@ -0,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 "@" diff --git a/engine/battle/moveEffects/leech_seed_effect.asm b/engine/battle/moveEffects/leech_seed_effect.asm new file mode 100644 index 00000000..a257d143 --- /dev/null +++ b/engine/battle/moveEffects/leech_seed_effect.asm @@ -0,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 "@" diff --git a/engine/battle/moveEffects/substitute_effect.asm b/engine/battle/moveEffects/substitute_effect.asm new file mode 100644 index 00000000..e88def4a --- /dev/null +++ b/engine/battle/moveEffects/substitute_effect.asm @@ -0,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 "@" diff --git a/engine/battle/print_type.asm b/engine/battle/print_type.asm new file mode 100644 index 00000000..38c701a8 --- /dev/null +++ b/engine/battle/print_type.asm @@ -0,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" diff --git a/engine/battle/save_trainer_name.asm b/engine/battle/save_trainer_name.asm new file mode 100644 index 00000000..84ef1f69 --- /dev/null +++ b/engine/battle/save_trainer_name.asm @@ -0,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♀@" -- cgit v1.2.3 From 77d0e5ff84cc61ae625da19f184094241eddd4dc Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 16:16:43 +0200 Subject: Rename battle files and split move effects Part 3 b.asm, b_2.asm, c.asm, and d.asm --- engine/battle/b.asm | 18 ---- engine/battle/b_2.asm | 129 ------------------------ engine/battle/c.asm | 58 ----------- engine/battle/d.asm | 23 ----- engine/battle/display_effectiveness.asm | 18 ++++ engine/battle/link_battle_versus_text.asm | 23 +++++ engine/battle/moveEffects/mist_effect.asm | 21 ++++ engine/battle/moveEffects/one_hit_ko_effect.asm | 36 +++++++ engine/battle/moveEffects/pay_day_effect.asm | 43 ++++++++ engine/battle/scale_sprites.asm | 85 ++++++++++++++++ 10 files changed, 226 insertions(+), 228 deletions(-) delete mode 100755 engine/battle/b.asm delete mode 100755 engine/battle/b_2.asm delete mode 100755 engine/battle/c.asm delete mode 100755 engine/battle/d.asm create mode 100644 engine/battle/display_effectiveness.asm create mode 100644 engine/battle/link_battle_versus_text.asm create mode 100644 engine/battle/moveEffects/mist_effect.asm create mode 100644 engine/battle/moveEffects/one_hit_ko_effect.asm create mode 100644 engine/battle/moveEffects/pay_day_effect.asm create mode 100644 engine/battle/scale_sprites.asm (limited to 'engine') diff --git a/engine/battle/b.asm b/engine/battle/b.asm deleted file mode 100755 index 17f0bd5b..00000000 --- a/engine/battle/b.asm +++ /dev/null @@ -1,18 +0,0 @@ -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 "@" diff --git a/engine/battle/b_2.asm b/engine/battle/b_2.asm deleted file mode 100755 index 4a49bb10..00000000 --- a/engine/battle/b_2.asm +++ /dev/null @@ -1,129 +0,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 "@" diff --git a/engine/battle/c.asm b/engine/battle/c.asm deleted file mode 100755 index b7c20ef6..00000000 --- a/engine/battle/c.asm +++ /dev/null @@ -1,58 +0,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 diff --git a/engine/battle/d.asm b/engine/battle/d.asm deleted file mode 100755 index 7320da29..00000000 --- a/engine/battle/d.asm +++ /dev/null @@ -1,23 +0,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 diff --git a/engine/battle/display_effectiveness.asm b/engine/battle/display_effectiveness.asm new file mode 100644 index 00000000..17f0bd5b --- /dev/null +++ b/engine/battle/display_effectiveness.asm @@ -0,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 "@" diff --git a/engine/battle/link_battle_versus_text.asm b/engine/battle/link_battle_versus_text.asm new file mode 100644 index 00000000..7320da29 --- /dev/null +++ b/engine/battle/link_battle_versus_text.asm @@ -0,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 diff --git a/engine/battle/moveEffects/mist_effect.asm b/engine/battle/moveEffects/mist_effect.asm new file mode 100644 index 00000000..adee1dfd --- /dev/null +++ b/engine/battle/moveEffects/mist_effect.asm @@ -0,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 "@" diff --git a/engine/battle/moveEffects/one_hit_ko_effect.asm b/engine/battle/moveEffects/one_hit_ko_effect.asm new file mode 100644 index 00000000..84418e33 --- /dev/null +++ b/engine/battle/moveEffects/one_hit_ko_effect.asm @@ -0,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 diff --git a/engine/battle/moveEffects/pay_day_effect.asm b/engine/battle/moveEffects/pay_day_effect.asm new file mode 100644 index 00000000..75a005ed --- /dev/null +++ b/engine/battle/moveEffects/pay_day_effect.asm @@ -0,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 "@" diff --git a/engine/battle/scale_sprites.asm b/engine/battle/scale_sprites.asm new file mode 100644 index 00000000..dae4ad42 --- /dev/null +++ b/engine/battle/scale_sprites.asm @@ -0,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 -- cgit v1.2.3 From 2fe782b11a039b52fd236da28fb2f1ae10cae7db Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 16:51:04 +0200 Subject: Rename battle files and split move effects Part 4 e.asm, e_2. asm, and 14.asm --- engine/battle/14.asm | 94 -- engine/battle/draw_hud_pokeball_gfx.asm | 191 +++ engine/battle/e.asm | 1569 -------------------- engine/battle/e_2.asm | 301 ---- engine/battle/init_battle_variables.asm | 40 + engine/battle/moveEffects/heal_effect.asm | 116 ++ engine/battle/moveEffects/paralyze_effect.asm | 53 + .../moveEffects/reflect_light_screen_effect.asm | 45 + engine/battle/moveEffects/transform_effect.asm | 138 ++ engine/battle/scroll_draw_trainer_pic.asm | 50 + engine/battle/trainer_party_ai_misc.asm | 1263 ++++++++++++++++ engine/battle/unused_stats_functions.asm | 62 + 12 files changed, 1958 insertions(+), 1964 deletions(-) delete mode 100755 engine/battle/14.asm create mode 100644 engine/battle/draw_hud_pokeball_gfx.asm delete mode 100755 engine/battle/e.asm delete mode 100755 engine/battle/e_2.asm create mode 100644 engine/battle/init_battle_variables.asm create mode 100644 engine/battle/moveEffects/heal_effect.asm create mode 100644 engine/battle/moveEffects/paralyze_effect.asm create mode 100644 engine/battle/moveEffects/reflect_light_screen_effect.asm create mode 100644 engine/battle/moveEffects/transform_effect.asm create mode 100644 engine/battle/scroll_draw_trainer_pic.asm create mode 100644 engine/battle/trainer_party_ai_misc.asm create mode 100644 engine/battle/unused_stats_functions.asm (limited to 'engine') diff --git a/engine/battle/14.asm b/engine/battle/14.asm deleted file mode 100755 index 1b2d7462..00000000 --- a/engine/battle/14.asm +++ /dev/null @@ -1,94 +0,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 diff --git a/engine/battle/draw_hud_pokeball_gfx.asm b/engine/battle/draw_hud_pokeball_gfx.asm new file mode 100644 index 00000000..fce3701c --- /dev/null +++ b/engine/battle/draw_hud_pokeball_gfx.asm @@ -0,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" diff --git a/engine/battle/e.asm b/engine/battle/e.asm deleted file mode 100755 index 1144abe8..00000000 --- a/engine/battle/e.asm +++ /dev/null @@ -1,1569 +0,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, 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 - -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" diff --git a/engine/battle/e_2.asm b/engine/battle/e_2.asm deleted file mode 100755 index 9400282d..00000000 --- a/engine/battle/e_2.asm +++ /dev/null @@ -1,301 +0,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 diff --git a/engine/battle/init_battle_variables.asm b/engine/battle/init_battle_variables.asm new file mode 100644 index 00000000..457cc4e1 --- /dev/null +++ b/engine/battle/init_battle_variables.asm @@ -0,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 diff --git a/engine/battle/moveEffects/heal_effect.asm b/engine/battle/moveEffects/heal_effect.asm new file mode 100644 index 00000000..22d482e7 --- /dev/null +++ b/engine/battle/moveEffects/heal_effect.asm @@ -0,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 "@" diff --git a/engine/battle/moveEffects/paralyze_effect.asm b/engine/battle/moveEffects/paralyze_effect.asm new file mode 100644 index 00000000..69acbb01 --- /dev/null +++ b/engine/battle/moveEffects/paralyze_effect.asm @@ -0,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 diff --git a/engine/battle/moveEffects/reflect_light_screen_effect.asm b/engine/battle/moveEffects/reflect_light_screen_effect.asm new file mode 100644 index 00000000..39a2c154 --- /dev/null +++ b/engine/battle/moveEffects/reflect_light_screen_effect.asm @@ -0,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 diff --git a/engine/battle/moveEffects/transform_effect.asm b/engine/battle/moveEffects/transform_effect.asm new file mode 100644 index 00000000..6e25712a --- /dev/null +++ b/engine/battle/moveEffects/transform_effect.asm @@ -0,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 "@" diff --git a/engine/battle/scroll_draw_trainer_pic.asm b/engine/battle/scroll_draw_trainer_pic.asm new file mode 100644 index 00000000..18df86e0 --- /dev/null +++ b/engine/battle/scroll_draw_trainer_pic.asm @@ -0,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 diff --git a/engine/battle/trainer_party_ai_misc.asm b/engine/battle/trainer_party_ai_misc.asm new file mode 100644 index 00000000..8cbb9329 --- /dev/null +++ b/engine/battle/trainer_party_ai_misc.asm @@ -0,0 +1,1263 @@ +; 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 + +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 "@" diff --git a/engine/battle/unused_stats_functions.asm b/engine/battle/unused_stats_functions.asm new file mode 100644 index 00000000..23ddbc20 --- /dev/null +++ b/engine/battle/unused_stats_functions.asm @@ -0,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 -- cgit v1.2.3 From 10211cc461b35140c815e18e95f7070eb0dcc586 Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 17:03:05 +0200 Subject: Rename battle files and split move effects Part 5 15.asm, 16.asm, 1a.asm, 1c.asm --- engine/battle/15.asm | 372 -------------- engine/battle/16.asm | 238 --------- engine/battle/1a.asm | 43 -- engine/battle/1c.asm | 905 ----------------------------------- engine/battle/battle_transitions.asm | 815 +++++++++++++++++++++++++++++++ engine/battle/common_text.asm | 238 +++++++++ engine/battle/decrement_pp.asm | 43 ++ engine/battle/experience.asm | 372 ++++++++++++++ engine/battle/ghost_marowak_anim.asm | 89 ++++ 9 files changed, 1557 insertions(+), 1558 deletions(-) delete mode 100755 engine/battle/15.asm delete mode 100755 engine/battle/16.asm delete mode 100755 engine/battle/1a.asm delete mode 100755 engine/battle/1c.asm create mode 100644 engine/battle/battle_transitions.asm create mode 100644 engine/battle/common_text.asm create mode 100644 engine/battle/decrement_pp.asm create mode 100644 engine/battle/experience.asm create mode 100644 engine/battle/ghost_marowak_anim.asm (limited to 'engine') diff --git a/engine/battle/15.asm b/engine/battle/15.asm deleted file mode 100755 index 9bd67654..00000000 --- a/engine/battle/15.asm +++ /dev/null @@ -1,372 +0,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 [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 "@" diff --git a/engine/battle/16.asm b/engine/battle/16.asm deleted file mode 100755 index 9a00bd98..00000000 --- a/engine/battle/16.asm +++ /dev/null @@ -1,238 +0,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 "@" diff --git a/engine/battle/1a.asm b/engine/battle/1a.asm deleted file mode 100755 index ecf5040b..00000000 --- a/engine/battle/1a.asm +++ /dev/null @@ -1,43 +0,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 diff --git a/engine/battle/1c.asm b/engine/battle/1c.asm deleted file mode 100755 index ce0296f7..00000000 --- a/engine/battle/1c.asm +++ /dev/null @@ -1,905 +0,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 diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm new file mode 100644 index 00000000..f1aa4161 --- /dev/null +++ b/engine/battle/battle_transitions.asm @@ -0,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 diff --git a/engine/battle/common_text.asm b/engine/battle/common_text.asm new file mode 100644 index 00000000..9a00bd98 --- /dev/null +++ b/engine/battle/common_text.asm @@ -0,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 "@" diff --git a/engine/battle/decrement_pp.asm b/engine/battle/decrement_pp.asm new file mode 100644 index 00000000..ecf5040b --- /dev/null +++ b/engine/battle/decrement_pp.asm @@ -0,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 diff --git a/engine/battle/experience.asm b/engine/battle/experience.asm new file mode 100644 index 00000000..9bd67654 --- /dev/null +++ b/engine/battle/experience.asm @@ -0,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 "@" diff --git a/engine/battle/ghost_marowak_anim.asm b/engine/battle/ghost_marowak_anim.asm new file mode 100644 index 00000000..73d3bcc2 --- /dev/null +++ b/engine/battle/ghost_marowak_anim.asm @@ -0,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 -- cgit v1.2.3 From ce9940a2eb89caa9f53507a6d6071f8eaf85ee48 Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 17:27:51 +0200 Subject: Further split bank e stuff --- engine/battle/bank_e_misc.asm | 122 +++ engine/battle/read_trainer_party.asm | 164 ++++ engine/battle/trainer_ai.asm | 837 +++++++++++++++++ engine/battle/trainer_party_ai_misc.asm | 1263 -------------------------- engine/battle/trainer_pic_money_pointers.asm | 143 +++ 5 files changed, 1266 insertions(+), 1263 deletions(-) create mode 100644 engine/battle/bank_e_misc.asm create mode 100644 engine/battle/read_trainer_party.asm create mode 100644 engine/battle/trainer_ai.asm delete mode 100644 engine/battle/trainer_party_ai_misc.asm create mode 100644 engine/battle/trainer_pic_money_pointers.asm (limited to 'engine') diff --git a/engine/battle/bank_e_misc.asm b/engine/battle/bank_e_misc.asm new file mode 100644 index 00000000..78b27108 --- /dev/null +++ b/engine/battle/bank_e_misc.asm @@ -0,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 diff --git a/engine/battle/read_trainer_party.asm b/engine/battle/read_trainer_party.asm new file mode 100644 index 00000000..f1e3aaf1 --- /dev/null +++ b/engine/battle/read_trainer_party.asm @@ -0,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 diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm new file mode 100644 index 00000000..191cfd5e --- /dev/null +++ b/engine/battle/trainer_ai.asm @@ -0,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 "@" diff --git a/engine/battle/trainer_party_ai_misc.asm b/engine/battle/trainer_party_ai_misc.asm deleted file mode 100644 index 8cbb9329..00000000 --- a/engine/battle/trainer_party_ai_misc.asm +++ /dev/null @@ -1,1263 +0,0 @@ -; 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 - -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 "@" diff --git a/engine/battle/trainer_pic_money_pointers.asm b/engine/battle/trainer_pic_money_pointers.asm new file mode 100644 index 00000000..3d32eb00 --- /dev/null +++ b/engine/battle/trainer_pic_money_pointers.asm @@ -0,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 -- cgit v1.2.3