diff options
| author | luckytyphlosion <alan.rj.huang@gmail.com> | 2016-01-16 15:16:13 -0500 | 
|---|---|---|
| committer | luckytyphlosion <alan.rj.huang@gmail.com> | 2016-01-16 15:16:13 -0500 | 
| commit | 02598831824a605fe66fe09dcdef7ad399dc0d7d (patch) | |
| tree | f969d2a7916010308633f25c970610d1a484d981 | |
| parent | 0962135bdbed24c53b58f8b1340b4a6d1af9ce27 (diff) | |
More bankF documentation.
PrintCriticalOHKOText to AdjustDamageForMoveType
| -rwxr-xr-x | engine/battle/core.asm | 172 | ||||
| -rw-r--r-- | engine/battle/core_.asm | 1415 | ||||
| -rw-r--r-- | engine/battle/moveEffects/heal_effect.asm | 2 | ||||
| -rw-r--r-- | engine/battle/moveEffects/paralyze_effect.asm | 2 | ||||
| -rw-r--r-- | engine/battle/moveEffects/recoil_effect.asm | 2 | ||||
| -rw-r--r-- | engine/battle/print_type.asm | 2 | ||||
| -rw-r--r-- | engine/battle/trainer_ai.asm | 4 | ||||
| -rwxr-xr-x | engine/items/items.asm | 8 | ||||
| -rwxr-xr-x | wram.asm | 8 | ||||
| -rwxr-xr-x | yellow/main.asm | 4 | 
10 files changed, 1497 insertions, 122 deletions
| diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 0efb7ac2..060f08bc 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -1863,7 +1863,7 @@ SendOutMon: ; 3ccfb (f:4cfb)  	ld [hl], a  	ld [wBoostExpByExpAll], a  	ld [wDamageMultipliers], a -	ld [W_PLAYERMOVENUM], a +	ld [wPlayerMoveNum], a  	ld hl, wPlayerUsedMove  	ld [hli], a  	ld [hl], a @@ -3379,7 +3379,7 @@ playPlayerMoveAnimation  	call nz,Bankswitch  	pop af  	ld [wAnimationType],a -	ld a,[W_PLAYERMOVENUM] +	ld a,[wPlayerMoveNum]  	call PlayMoveAnimation  	call HandleExplodingAnimation  	call DrawPlayerHUDAndHPBar @@ -3691,7 +3691,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854)  	bit StoringEnergy,[hl] ; is mon using bide?  	jr z,.ThrashingAboutCheck  	xor a -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	ld hl,wDamage  	ld a,[hli]  	ld b,a @@ -3714,7 +3714,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854)  	ld hl,UnleashedEnergyText  	call PrintText  	ld a,1 -	ld [W_PLAYERMOVEPOWER],a +	ld [wPlayerMovePower],a  	ld hl,wPlayerBideAccumulatedDamage + 1  	ld a,[hld]  	add a @@ -3732,7 +3732,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854)  	ld [hli],a  	ld [hl],a  	ld a,BIDE -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	ld hl,handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest  	jp .returnToHL @@ -3740,7 +3740,7 @@ CheckPlayerStatusConditions: ; 3d854 (f:5854)  	bit ThrashingAbout,[hl] ; is mon using thrash or petal dance?  	jr z,.MultiturnMoveCheck  	ld a,THRASH -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	ld hl,ThrashingAboutText  	call PrintText  	ld hl,wPlayerNumAttacksLeft @@ -3934,7 +3934,7 @@ MonName1Text: ; 3dafb (f:5afb)  	TX_ASM  	ld a, [H_WHOSETURN]  	and a -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	ld hl, wPlayerUsedMove  	jr z, .asm_3db11  	ld a, [wEnemyMoveNum] @@ -4145,7 +4145,7 @@ DoesntAffectMonText: ; 3dc57 (f:5c57)  	db "@"  ; if there was a critical hit or an OHKO was successful, print the corresponding text -PrintCriticalOHKOText: ; 3dc5c (f:5c5c) +PrintCriticalOHKOText: ; 3ddce (f:5dce)  	ld a, [wCriticalHitOrOHKO]  	and a  	jr z, .done ; do nothing if there was no critical hit or successful OHKO @@ -4165,21 +4165,21 @@ PrintCriticalOHKOText: ; 3dc5c (f:5c5c)  	ld c, 20  	jp DelayFrames -CriticalOHKOTextPointers: ; 3dc7a (f:5c7a) +CriticalOHKOTextPointers: ; 3ddec (f:5dec)  	dw CriticalHitText  	dw OHKOText -CriticalHitText: ; 3dc7e (f:5c7e) +CriticalHitText: ; 3ddf0 (f:5df0)  	TX_FAR _CriticalHitText  	db "@" -OHKOText: ; 3dc83 (f:5c83) +OHKOText: ; 3ddf5 (f:5df5)  	TX_FAR _OHKOText  	db "@"  ; checks if a traded mon will disobey due to lack of badges  ; stores whether the mon will use a move in Z flag -CheckForDisobedience: ; 3dc88 (f:5c88) +CheckForDisobedience: ; 3ddfa (f:5dfa)  	xor a  	ld [wMonIsDisobedient], a  	ld a, [wLinkState] @@ -4358,38 +4358,38 @@ CheckForDisobedience: ; 3dc88 (f:5c88)  	xor a ; set Z flag  	ret -LoafingAroundText: ; 3ddb6 (f:5db6) +LoafingAroundText: ; 3df28 (f:5f28)  	TX_FAR _LoafingAroundText  	db "@" -BeganToNapText: ; 3ddbb (f:5dbb) +BeganToNapText: ; 3df2d (f:5f2d)  	TX_FAR _BeganToNapText  	db "@" -WontObeyText: ; 3ddc0 (f:5dc0) +WontObeyText: ; 3df32 (f:5f32)  	TX_FAR _WontObeyText  	db "@" -TurnedAwayText: ; 3ddc5 (f:5dc5) +TurnedAwayText: ; 3df37 (f:5f37)  	TX_FAR _TurnedAwayText  	db "@" -IgnoredOrdersText: ; 3ddca (f:5dca) +IgnoredOrdersText: ; 3df3c (f:5f3c)  	TX_FAR _IgnoredOrdersText  	db "@"  ; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the player mon -GetDamageVarsForPlayerAttack: ; 3ddcf (f:5dcf) +GetDamageVarsForPlayerAttack: ; 3df41 (f:5f41)  	xor a  	ld hl, wDamage ; damage to eventually inflict, initialise to zero  	ldi [hl], a  	ld [hl], a -	ld hl, W_PLAYERMOVEPOWER +	ld hl, wPlayerMovePower  	ld a, [hli]  	and a  	ld d, a ; d = move power  	ret z ; return if move power is zero -	ld a, [hl] ; a = [W_PLAYERMOVETYPE] +	ld a, [hl] ; a = [wPlayerMoveType]  	cp FIRE ; types >= FIRE are all special  	jr nc, .specialAttack  .physicalAttack @@ -4492,12 +4492,12 @@ GetDamageVarsForPlayerAttack: ; 3ddcf (f:5dcf)  	ret  ; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the enemy mon -GetDamageVarsForEnemyAttack: ; 3de75 (f:5e75) +GetDamageVarsForEnemyAttack: ; 3dfe7 (f:5fe7)  	ld hl, wDamage ; damage to eventually inflict, initialise to zero  	xor a  	ld [hli], a  	ld [hl], a -	ld hl, W_ENEMYMOVEPOWER +	ld hl, wEnemyMovePower  	ld a, [hli]  	ld d, a ; d = move power  	and a @@ -4607,7 +4607,7 @@ GetDamageVarsForEnemyAttack: ; 3de75 (f:5e75)  ; get stat c of enemy mon  ; c: stat to get (HP=1,Attack=2,Defense=3,Speed=4,Special=5) -GetEnemyMonStat: ; 3df1c (f:5f1c) +GetEnemyMonStat: ; 3e08e (f:608e)  	push de  	push bc  	ld a, [wLinkState] @@ -4648,7 +4648,7 @@ GetEnemyMonStat: ; 3df1c (f:5f1c)  	pop de  	ret -CalculateDamage: ; 3df65 (f:5f65) +CalculateDamage: ; 3d0d7 (f:60d7)  ; input:  ;	b: attack  ;	c: opponent defense @@ -4741,31 +4741,31 @@ CalculateDamage: ; 3df65 (f:5f65)  	ld a, [H_QUOTIENT + 3]  	add b  	ld [H_QUOTIENT + 3], a -	jr nc, .asm_3dfd0 +	jr nc, .asm_3e142  	ld a, [H_QUOTIENT + 2]  	inc a  	ld [H_QUOTIENT + 2], a  	and a -	jr z, .asm_3e004 +	jr z, .asm_3e176 -.asm_3dfd0 +.asm_3e142  	ld a, [H_QUOTIENT]  	ld b, a  	ld a, [H_QUOTIENT + 1]  	or a -	jr nz, .asm_3e004 +	jr nz, .asm_3e176  	ld a, [H_QUOTIENT + 2]  	cp 998 / $100 -	jr c, .asm_3dfe8 +	jr c, .asm_3e15a  	cp 998 / $100 + 1 -	jr nc, .asm_3e004 +	jr nc, .asm_3e176  	ld a, [H_QUOTIENT + 3]  	cp 998 % $100 -	jr nc, .asm_3e004 +	jr nc, .asm_3e176 -.asm_3dfe8 +.asm_3e15a  	inc hl  	ld a, [H_QUOTIENT + 3]  	ld b, [hl] @@ -4776,26 +4776,26 @@ CalculateDamage: ; 3df65 (f:5f65)  	ld b, [hl]  	adc b  	ld [hl], a -	jr c, .asm_3e004 +	jr c, .asm_3e176  	ld a, [hl]  	cp 998 / $100 -	jr c, .asm_3e00a +	jr c, .asm_3e17c  	cp 998 / $100 + 1 -	jr nc, .asm_3e004 +	jr nc, .asm_3e176  	inc hl  	ld a, [hld]  	cp 998 % $100 -	jr c, .asm_3e00a +	jr c, .asm_3e17c -.asm_3e004 +.asm_3e176  ; cap at 997  	ld a, 997 / $100  	ld [hli], a  	ld a, 997 % $100  	ld [hld], a -.asm_3e00a +.asm_3e17c  ; add 2  	inc hl  	ld a, [hl] @@ -4810,14 +4810,14 @@ CalculateDamage: ; 3df65 (f:5f65)  	and a  	ret -JumpToOHKOMoveEffect: ; 3e016 (f:6016) +JumpToOHKOMoveEffect: ; 3e188 (f:6188)  	call JumpMoveEffect  	ld a, [wMoveMissed]  	dec a  	ret -UnusedHighCriticalMoves: ; 3e01e (f:601e) +UnusedHighCriticalMoves: ; 3e190 (f:6190)  	db KARATE_CHOP  	db RAZOR_LEAF  	db CRABHAMMER @@ -4826,17 +4826,17 @@ UnusedHighCriticalMoves: ; 3e01e (f:601e)  ; 3e023  ; determines if attack is a critical hit -; azure heights claims "the fastest pokémon (who are,not coincidentally, +; azure heights claims "the fastest pokémon (who are, not coincidentally,  ; among the most popular) tend to CH about 20 to 25% of the time." -CriticalHitTest: ; 3e023 (f:6023) +CriticalHitTest: ; 3e195 (f:6195)  	xor a  	ld [wCriticalHitOrOHKO], a  	ld a, [H_WHOSETURN]  	and a  	ld a, [wEnemyMonSpecies] -	jr nz, .asm_3e032 +	jr nz, .handleEnemy  	ld a, [wBattleMonSpecies] -.asm_3e032 +.handleEnemy  	ld [wd0b5], a  	call GetMonHeader  	ld a, [wMonHBaseSpeed] @@ -4844,10 +4844,10 @@ CriticalHitTest: ; 3e023 (f:6023)  	srl b                        ; (effective (base speed/2))  	ld a, [H_WHOSETURN]  	and a -	ld hl, W_PLAYERMOVEPOWER +	ld hl, wPlayerMovePower  	ld de, wPlayerBattleStatus2  	jr z, .calcCriticalHitProbability -	ld hl, W_ENEMYMOVEPOWER +	ld hl, wEnemyMovePower  	ld de, wEnemyBattleStatus2  .calcCriticalHitProbability  	ld a, [hld]                  ; read base power from RAM @@ -4895,7 +4895,7 @@ CriticalHitTest: ; 3e023 (f:6023)  	ret  ; high critical hit moves -HighCriticalMoves: ; 3e08e (f:608e) +HighCriticalMoves: ; 3e200 (f:6200)  	db KARATE_CHOP  	db RAZOR_LEAF  	db CRABHAMMER @@ -4904,7 +4904,7 @@ HighCriticalMoves: ; 3e08e (f:608e)  ; function to determine if Counter hits and if so, how much damage it does -HandleCounterMove: ; 3e093 (f:6093) +HandleCounterMove: ; 3e205 (f:6205)  ; The variables checked by Counter are updated whenever the cursor points to a new move in the battle selection menu.  ; This is irrelevant for the opponent's side outside of link battles, since the move selection is controlled by the AI.  ; However, in the scenario where the player switches out and the opponent uses Counter, @@ -4915,12 +4915,12 @@ HandleCounterMove: ; 3e093 (f:6093)  	and a  ; player's turn  	ld hl,wEnemySelectedMove -	ld de,W_ENEMYMOVEPOWER +	ld de,wEnemyMovePower  	ld a,[wPlayerSelectedMove]  	jr z,.next  ; enemy's turn  	ld hl,wPlayerSelectedMove -	ld de,W_PLAYERMOVEPOWER +	ld de,wPlayerMovePower  	ld a,[wEnemySelectedMove]  .next  	cp a,COUNTER @@ -4969,7 +4969,7 @@ HandleCounterMove: ; 3e093 (f:6093)  	xor a  	ret -ApplyAttackToEnemyPokemon: ; 3e0df (f:60df) +ApplyAttackToEnemyPokemon: ; 3e251 (f:6251)  	ld a,[wPlayerMoveEffect]  	cp a,OHKO_EFFECT  	jr z,ApplyDamageToEnemyPokemon @@ -4977,7 +4977,7 @@ ApplyAttackToEnemyPokemon: ; 3e0df (f:60df)  	jr z,.superFangEffect  	cp a,SPECIAL_DAMAGE_EFFECT  	jr z,.specialDamage -	ld a,[W_PLAYERMOVEPOWER] +	ld a,[wPlayerMovePower]  	and a  	jp z,ApplyAttackToEnemyPokemonDone ; no attack to apply if base power is 0  	jr ApplyDamageToEnemyPokemon @@ -5003,7 +5003,7 @@ ApplyAttackToEnemyPokemon: ; 3e0df (f:60df)  	ld hl,wBattleMonLevel  	ld a,[hl]  	ld b,a ; Seismic Toss deals damage equal to the user's level -	ld a,[W_PLAYERMOVENUM] +	ld a,[wPlayerMoveNum]  	cp a,SEISMIC_TOSS  	jr z,.storeDamage  	cp a,NIGHT_SHADE @@ -5035,7 +5035,7 @@ ApplyAttackToEnemyPokemon: ; 3e0df (f:60df)  	ld a,b  	ld [hl],a -ApplyDamageToEnemyPokemon: ; 3e142 (f:6142) +ApplyDamageToEnemyPokemon: ; 3e2b4 (f:62b4)  	ld hl,wDamage  	ld a,[hli]  	ld b,a @@ -5085,10 +5085,10 @@ ApplyDamageToEnemyPokemon: ; 3e142 (f:6142)  	xor a  	ld [wHPBarType],a  	predef UpdateHPBar2 ; animate the HP bar shortening -ApplyAttackToEnemyPokemonDone: ; 3e19d (f:619d) +ApplyAttackToEnemyPokemonDone: ; 3e30f (f:630f)  	jp DrawHUDsAndHPBars -ApplyAttackToPlayerPokemon: ; 3e1a0 (f:61a0) +ApplyAttackToPlayerPokemon: ; 3e312 (f:6312)  	ld a,[wEnemyMoveEffect]  	cp a,OHKO_EFFECT  	jr z,ApplyDamageToPlayerPokemon @@ -5096,7 +5096,7 @@ ApplyAttackToPlayerPokemon: ; 3e1a0 (f:61a0)  	jr z,.superFangEffect  	cp a,SPECIAL_DAMAGE_EFFECT  	jr z,.specialDamage -	ld a,[W_ENEMYMOVEPOWER] +	ld a,[wEnemyMovePower]  	and a  	jp z,ApplyAttackToPlayerPokemonDone  	jr ApplyDamageToPlayerPokemon @@ -5154,7 +5154,7 @@ ApplyAttackToPlayerPokemon: ; 3e1a0 (f:61a0)  	ld a,b  	ld [hl],a -ApplyDamageToPlayerPokemon: ; 3e200 (f:6200) +ApplyDamageToPlayerPokemon: ; 3e372 (f:6372)  	ld hl,wDamage  	ld a,[hli]  	ld b,a @@ -5203,10 +5203,10 @@ ApplyDamageToPlayerPokemon: ; 3e200 (f:6200)  	ld a,$01  	ld [wHPBarType],a  	predef UpdateHPBar2 ; animate the HP bar shortening -ApplyAttackToPlayerPokemonDone +ApplyAttackToPlayerPokemonDone: ; 3e3cd (f:63cd)  	jp DrawHUDsAndHPBars -AttackSubstitute: ; 3e25e (f:625e) +AttackSubstitute: ; 3e3d0 (f:63d0)  ; 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, @@ -5261,16 +5261,16 @@ AttackSubstitute: ; 3e25e (f:625e)  	ld [hl],a ; zero the effect of the attacker's move  	jp DrawHUDsAndHPBars -SubstituteTookDamageText: ; 3e2ac (f:62ac) +SubstituteTookDamageText: ; 3e41e (f:641e)  	TX_FAR _SubstituteTookDamageText  	db "@" -SubstituteBrokeText: ; 3e2b1 (f:62b1) +SubstituteBrokeText: ; 3e423 (f:6423)  	TX_FAR _SubstituteBrokeText  	db "@"  ; this function raises the attack modifier of a pokemon using Rage when that pokemon is attacked -HandleBuildingRage: ; 3e2b6 (f:62b6) +HandleBuildingRage: ; 3e428 (f:6428)  ; values for the player turn  	ld hl,wEnemyBattleStatus2  	ld de,wEnemyMonStatMods @@ -5281,7 +5281,7 @@ HandleBuildingRage: ; 3e2b6 (f:62b6)  ; values for the enemy turn  	ld hl,wPlayerBattleStatus2  	ld de,wPlayerMonStatMods -	ld bc,W_PLAYERMOVENUM +	ld bc,wPlayerMoveNum  .next  	bit UsingRage,[hl] ; is the pokemon being attacked under the effect of Rage?  	ret z ; return if not @@ -5312,13 +5312,13 @@ HandleBuildingRage: ; 3e2b6 (f:62b6)  	ld [H_WHOSETURN],a  	ret -BuildingRageText: ; 3e2f8 (f:62f8) +BuildingRageText: ; 3e46a (f:646a)  	TX_FAR _BuildingRageText  	db "@"  ; copy last move for Mirror Move  ; sets zero flag on failure and unsets zero flag on success -MirrorMoveCopyMove: ; 3e2fd (f:62fd) +MirrorMoveCopyMove: ; 3e46f (f:646f)  ; Mirror Move makes use of ccf1 (wPlayerUsedMove) and ccf2 (wEnemyUsedMove) addresses,  ; which are mainly used to print the "[Pokemon] used [Move]" text.  ; Both are set to 0 whenever a new Pokemon is sent out @@ -5330,7 +5330,7 @@ MirrorMoveCopyMove: ; 3e2fd (f:62fd)  ; values for player turn  	ld a,[wEnemyUsedMove]  	ld hl,wPlayerSelectedMove -	ld de,W_PLAYERMOVENUM +	ld de,wPlayerMoveNum  	jr z,.next  ; values for enemy turn  	ld a,[wPlayerUsedMove] @@ -5348,12 +5348,12 @@ MirrorMoveCopyMove: ; 3e2fd (f:62fd)  	xor a  	ret -MirrorMoveFailedText: ; 3e324 (f:6324) +MirrorMoveFailedText: ; 3e496 (f:6496)  	TX_FAR _MirrorMoveFailedText  	db "@"  ; function used to reload move data for moves like Mirror Move and Metronome -ReloadMoveData: ; 3e329 (f:6329) +ReloadMoveData: ; 3e49b (f:649b)  	ld [wd11e],a  	dec a  	ld hl,Moves @@ -5370,13 +5370,13 @@ ReloadMoveData: ; 3e329 (f:6329)  	ret  ; function that picks a random move for metronome -MetronomePickMove: ; 3e348 (f:6348) +MetronomePickMove: ; 3e4ba (f:64ba)  	xor a  	ld [wAnimationType],a  	ld a,METRONOME  	call PlayMoveAnimation ; play Metronome's animation  ; values for player turn -	ld de,W_PLAYERMOVENUM +	ld de,wPlayerMoveNum  	ld hl,wPlayerSelectedMove  	ld a,[H_WHOSETURN]  	and a @@ -5399,7 +5399,7 @@ MetronomePickMove: ; 3e348 (f:6348)  ; this function increments the current move's PP  ; it's used to prevent moves that run another move within the same turn  ; (like Mirror Move and Metronome) from losing 2 PP -IncrementMovePP: ; 3e373 (f:6373) +IncrementMovePP: ; 3e4e5 (f:64e5)  	ld a,[H_WHOSETURN]  	and a  ; values for player turn @@ -5431,7 +5431,7 @@ IncrementMovePP: ; 3e373 (f:6373)  	ret  ; function to adjust the base damage of an attack to account for type effectiveness -AdjustDamageForMoveType: ; 3e3a5 (f:63a5) +AdjustDamageForMoveType: ; 3e517 (f:6517)  ; values for player turn  	ld hl,wBattleMonType  	ld a,[hli] @@ -5441,7 +5441,7 @@ AdjustDamageForMoveType: ; 3e3a5 (f:63a5)  	ld a,[hli]  	ld d,a    ; d = type 1 of defender  	ld e,[hl] ; e = type 2 of defender -	ld a,[W_PLAYERMOVETYPE] +	ld a,[wPlayerMoveType]  	ld [wMoveType],a  	ld a,[H_WHOSETURN]  	and a @@ -5550,7 +5550,7 @@ AdjustDamageForMoveType: ; 3e3a5 (f:63a5)  ; the result is stored in [wTypeEffectiveness]  ; ($05 is not very effective, $10 is neutral, $14 is super effective)  ; as far is can tell, this is only used once in some AI code to help decide which move to use -AIGetTypeEffectiveness: ; 3e449 (f:6449) +AIGetTypeEffectiveness: ; 3e5bb (f:65bb)  	ld a,[wEnemyMoveType]  	ld d,a                    ; d = type of enemy move  	ld hl,wBattleMonType @@ -6240,7 +6240,7 @@ CheckEnemyStatusConditions: ; 3e88f (f:688f)  	ld hl, UnleashedEnergyText  	call PrintText  	ld a, $1 -	ld [W_ENEMYMOVEPOWER], a +	ld [wEnemyMovePower], a  	ld hl, wEnemyBideAccumulatedDamage + 1  	ld a, [hld]  	add a @@ -6323,7 +6323,7 @@ GetCurrentMove: ; 3eabe (f:6abe)  	ld a, [wEnemySelectedMove]  	jr .selected  .player -	ld de, W_PLAYERMOVENUM +	ld de, wPlayerMoveNum  	ld a, [wFlags_D733]  	bit BIT_TEST_BATTLE, a  	ld a, [wTestBattlePlayerSelectedMove] @@ -6952,7 +6952,7 @@ HandleExplodingAnimation: ; 3eed3 (f:6ed3)  	and a  	ld hl, wEnemyMonType1  	ld de, wEnemyBattleStatus1 -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	jr z, .asm_3eeea  	ld hl, wBattleMonType1  	ld de, wEnemyBattleStatus1 @@ -7280,7 +7280,7 @@ FreezeBurnParalyzeEffect: ; 3f30c (f:730c)  	ld a, [wEnemyMonStatus]  	and a  	jp nz, CheckDefrost ; can't inflict status if opponent is already statused -	ld a, [W_PLAYERMOVETYPE] +	ld a, [wPlayerMoveType]  	ld b, a  	ld a, [wEnemyMonType1]  	cp b ; do target type 1 and move type match? @@ -7390,7 +7390,7 @@ CheckDefrost: ; 3f3e2 (f:73e2)  	and a  	jr nz, .opponent  	;player [attacker] -	ld a, [W_PLAYERMOVETYPE] +	ld a, [wPlayerMoveType]  	sub a, FIRE  	ret nz ; return if type of move used isn't fire  	ld [wEnemyMonStatus], a	; set opponent status to 00 ["defrost" a frozen monster] @@ -7531,7 +7531,7 @@ UpdateStatDone: ; 3f4ca (f:74ca)  	inc b  	call PrintStatText  	ld hl, wPlayerBattleStatus2 -	ld de, W_PLAYERMOVENUM +	ld de, wPlayerMoveNum  	ld bc, wPlayerMonMinimized  	ld a, [H_WHOSETURN]  	and a @@ -7923,7 +7923,7 @@ SwitchAndTeleportEffect: ; 3f739 (f:7739)  	jr nc, .asm_3f76e  	ld c, 50  	call DelayFrames -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	cp TELEPORT  	jp nz, PrintDidntAffectText  	jp PrintButItFailedText_ @@ -7933,13 +7933,13 @@ SwitchAndTeleportEffect: ; 3f739 (f:7739)  	ld [wAnimationType], a  	inc a  	ld [wEscapedFromBattle], a -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	jr .asm_3f7e4  .asm_3f77e  	ld c, 50  	call DelayFrames  	ld hl, IsUnaffectedText -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	cp TELEPORT  	jp nz, PrintText  	jp PrintButItFailedText_ @@ -8540,7 +8540,7 @@ PlayCurrentMoveAnimation2: ; 3fb89 (f:7b89)  ; plays wAnimationType 3 or 6  	ld a, [H_WHOSETURN]  	and a -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	jr z, .notEnemyTurn  	ld a, [wEnemyMoveNum]  .notEnemyTurn @@ -8566,7 +8566,7 @@ PlayCurrentMoveAnimation: ; 3fba8 (f:7ba8)  	ld [wAnimationType], a  	ld a, [H_WHOSETURN]  	and a -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	jr z, .notEnemyTurn  	ld a, [wEnemyMoveNum]  .notEnemyTurn diff --git a/engine/battle/core_.asm b/engine/battle/core_.asm index 997a1c0c..188b41c3 100644 --- a/engine/battle/core_.asm +++ b/engine/battle/core_.asm @@ -1867,7 +1867,7 @@ SendOutMon: ; 3ccfb (f:4cfb)  	ld [hl], a  	ld [wBoostExpByExpAll], a  	ld [wDamageMultipliers], a -	ld [W_PLAYERMOVENUM], a +	ld [wPlayerMoveNum], a  	ld hl, wPlayerUsedMove  	ld [hli], a  	ld [hl], a @@ -3388,7 +3388,7 @@ playPlayerMoveAnimation ; 3d890 (f:5890)  	call nz,Bankswitch  	pop af  	ld [wAnimationType],a -	ld a,[W_PLAYERMOVENUM] +	ld a,[wPlayerMoveNum]  	call PlayMoveAnimation  	call HandleExplodingAnimation  	call DrawPlayerHUDAndHPBar @@ -3700,7 +3700,7 @@ CheckPlayerStatusConditions: ; 3d9c6 (f:59c6)  	bit StoringEnergy,[hl] ; is mon using bide?  	jr z,.ThrashingAboutCheck  	xor a -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	ld hl,wDamage  	ld a,[hli]  	ld b,a @@ -3723,7 +3723,7 @@ CheckPlayerStatusConditions: ; 3d9c6 (f:59c6)  	ld hl,UnleashedEnergyText  	call PrintText  	ld a,1 -	ld [W_PLAYERMOVEPOWER],a +	ld [wPlayerMovePower],a  	ld hl,wPlayerBideAccumulatedDamage + 1  	ld a,[hld]  	add a @@ -3741,7 +3741,7 @@ CheckPlayerStatusConditions: ; 3d9c6 (f:59c6)  	ld [hli],a  	ld [hl],a  	ld a,BIDE -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	ld hl,handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest  	jp .returnToHL @@ -3749,7 +3749,7 @@ CheckPlayerStatusConditions: ; 3d9c6 (f:59c6)  	bit ThrashingAbout,[hl] ; is mon using thrash or petal dance?  	jr z,.MultiturnMoveCheck  	ld a,THRASH -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	ld hl,ThrashingAboutText  	call PrintText  	ld hl,wPlayerNumAttacksLeft @@ -3943,7 +3943,7 @@ MonName1Text: ; 3dc6d (f:5c6d)  	TX_ASM  	ld a, [H_WHOSETURN]  	and a -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	ld hl, wPlayerUsedMove  	jr z, .playerTurn  	ld a, [wEnemyMoveNum] @@ -4155,32 +4155,1405 @@ DoesntAffectMonText: ; 3ddc9 (f:5dc9)  	TX_FAR _DoesntAffectMonText  	db "@" +; if there was a critical hit or an OHKO was successful, print the corresponding text  PrintCriticalOHKOText: ; 3ddce (f:5dce) -	dr $3ddce,$3ddfa +	ld a, [wCriticalHitOrOHKO] +	and a +	jr z, .done ; do nothing if there was no critical hit or successful OHKO +	dec a +	add a +	ld hl, CriticalOHKOTextPointers +	ld b, $0 +	ld c, a +	add hl, bc +	ld a, [hli] +	ld h, [hl] +	ld l, a +	call PrintText +	xor a +	ld [wCriticalHitOrOHKO], a +.done +	ld c, 20 +	jp DelayFrames + +CriticalOHKOTextPointers: ; 3ddec (f:5dec) +	dw CriticalHitText +	dw OHKOText + +CriticalHitText: ; 3ddf0 (f:5df0) +	TX_FAR _CriticalHitText +	db "@" + +OHKOText: ; 3ddf5 (f:5df5) +	TX_FAR _OHKOText +	db "@" + +; checks if a traded mon will disobey due to lack of badges +; stores whether the mon will use a move in Z flag  CheckForDisobedience: ; 3ddfa (f:5dfa) -	dr $3ddfa,$3df41 +	xor a +	ld [wMonIsDisobedient], a +	ld a, [wLinkState] +	cp LINK_STATE_BATTLING +	jr nz, .checkIfMonIsTraded +	ld a, $1 +	and a +	ret +; compare the mon's original trainer ID with the player's ID to see if it was traded +.checkIfMonIsTraded +	ld hl, wPartyMon1OTID +	ld bc, wPartyMon2 - wPartyMon1 +	ld a, [wPlayerMonNumber] +	call AddNTimes +	ld a, [wPlayerID] +	cp [hl] +	jr nz, .monIsTraded +	inc hl +	ld a, [wPlayerID + 1] +	cp [hl] +	jp z, .canUseMove +; it was traded +.monIsTraded +; what level might disobey? +	ld hl, wObtainedBadges +	bit 7, [hl] +	ld a, 101 +	jr nz, .next +	bit 5, [hl] +	ld a, 70 +	jr nz, .next +	bit 3, [hl] +	ld a, 50 +	jr nz, .next +	bit 1, [hl] +	ld a, 30 +	jr nz, .next +	ld a, 10 +.next +	ld b, a +	ld c, a +	ld a, [wBattleMonLevel] +	ld d, a +	add b +	ld b, a +	jr nc, .noCarry +	ld b, $ff ; cap b at $ff +.noCarry +	ld a, c +	cp d +	jp nc, .canUseMove +.loop1 +	call BattleRandom +	swap a +	cp b +	jr nc, .loop1 +	cp c +	jp c, .canUseMove +.loop2 +	call BattleRandom +	cp b +	jr nc, .loop2 +	cp c +	jr c, .useRandomMove +	ld a, d +	sub c +	ld b, a +	call BattleRandom +	swap a +	sub b +	jr c, .monNaps +	cp b +	jr nc, .monDoesNothing +	ld hl, WontObeyText +	call PrintText +	call HandleSelfConfusionDamage +	jp .cannotUseMove +.monNaps +	call BattleRandom +	add a +	swap a +	and SLP ; sleep mask +	jr z, .monNaps ; keep trying until we get at least 1 turn of sleep +	ld [wBattleMonStatus], a +	ld hl, BeganToNapText +	jr .printText +.monDoesNothing +	call BattleRandom +	and $3 +	ld hl, LoafingAroundText +	and a +	jr z, .printText +	ld hl, WontObeyText +	dec a +	jr z, .printText +	ld hl, TurnedAwayText +	dec a +	jr z, .printText +	ld hl, IgnoredOrdersText +.printText +	call PrintText +	jr .cannotUseMove +.useRandomMove +	ld a, [wBattleMonMoves + 1] +	and a ; is the second move slot empty? +	jr z, .monDoesNothing ; mon will not use move if it only knows one move +	ld a, [wPlayerDisabledMoveNumber] +	and a +	jr nz, .monDoesNothing +	ld a, [wPlayerSelectedMove] +	cp STRUGGLE +	jr z, .monDoesNothing ; mon will not use move if struggling +; check if only one move has remaining PP +	ld hl, wBattleMonPP +	push hl +	ld a, [hli] +	and $3f +	ld b, a +	ld a, [hli] +	and $3f +	add b +	ld b, a +	ld a, [hli] +	and $3f +	add b +	ld b, a +	ld a, [hl] +	and $3f +	add b +	pop hl +	push af +	ld a, [wCurrentMenuItem] +	ld c, a +	ld b, $0 +	add hl, bc +	ld a, [hl] +	and $3f +	ld b, a +	pop af +	cp b +	jr z, .monDoesNothing ; mon will not use move if only one move has remaining PP +	ld a, $1 +	ld [wMonIsDisobedient], a +	ld a, [wMaxMenuItem] +	ld b, a +	ld a, [wCurrentMenuItem] +	ld c, a +.chooseMove +	call BattleRandom +	and $3 +	cp b +	jr nc, .chooseMove ; if the random number is greater than the move count, choose another +	cp c +	jr z, .chooseMove ; if the random number matches the move the player selected, choose another +	ld [wCurrentMenuItem], a +	ld hl, wBattleMonPP +	ld e, a +	ld d, $0 +	add hl, de +	ld a, [hl] +	and a ; does the move have any PP left? +	jr z, .chooseMove ; if the move has no PP left, choose another +	ld a, [wCurrentMenuItem] +	ld c, a +	ld b, $0 +	ld hl, wBattleMonMoves +	add hl, bc +	ld a, [hl] +	ld [wPlayerSelectedMove], a +	call GetCurrentMove +.canUseMove +	ld a, $1 +	and a; clear Z flag +	ret +.cannotUseMove +	xor a ; set Z flag +	ret + +LoafingAroundText: ; 3df28 (f:5f28) +	TX_FAR _LoafingAroundText +	db "@" + +BeganToNapText: ; 3df2d (f:5f2d) +	TX_FAR _BeganToNapText +	db "@" + +WontObeyText: ; 3df32 (f:5f32) +	TX_FAR _WontObeyText +	db "@" + +TurnedAwayText: ; 3df37 (f:5f37) +	TX_FAR _TurnedAwayText +	db "@" + +IgnoredOrdersText: ; 3df3c (f:5f3c) +	TX_FAR _IgnoredOrdersText +	db "@" + +; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the player mon  GetDamageVarsForPlayerAttack: ; 3df41 (f:5f41) -	dr $3df41,$3e0d7 -CalculateDamage: ; 3e0d7 (f:60d7) -	dr $3e0d7,$3e195 +	xor a +	ld hl, wDamage ; damage to eventually inflict, initialise to zero +	ldi [hl], a +	ld [hl], a +	ld hl, wPlayerMovePower +	ld a, [hli] +	and a +	ld d, a ; d = move power +	ret z ; return if move power is zero +	ld a, [hl] ; a = [wPlayerMoveType] +	cp FIRE ; types >= FIRE are all special +	jr nc, .specialAttack +.physicalAttack +	ld hl, wEnemyMonDefense +	ld a, [hli] +	ld b, a +	ld c, [hl] ; bc = enemy defense +	ld a, [wEnemyBattleStatus3] +	bit HasReflectUp, a ; check for Reflect +	jr z, .physicalAttackCritCheck +; if the enemy has used Reflect, double the enemy's defense +	sla c +	rl b +.physicalAttackCritCheck +	ld hl, wBattleMonAttack +	ld a, [wCriticalHitOrOHKO] +	and a ; check for critical hit +	jr z, .scaleStats +; in the case of a critical hit, reset the player's attack and the enemy's defense to their base values +	ld c, 3 ; defense stat +	call GetEnemyMonStat +	ld a, [H_PRODUCT + 2] +	ld b, a +	ld a, [H_PRODUCT + 3] +	ld c, a +	push bc +	ld hl, wPartyMon1Attack +	ld a, [wPlayerMonNumber] +	ld bc, wPartyMon2 - wPartyMon1 +	call AddNTimes +	pop bc +	jr .scaleStats +.specialAttack +	ld hl, wEnemyMonSpecial +	ld a, [hli] +	ld b, a +	ld c, [hl] ; bc = enemy special +	ld a, [wEnemyBattleStatus3] +	bit HasLightScreenUp, a ; check for Light Screen +	jr z, .specialAttackCritCheck +; if the enemy has used Light Screen, double the enemy's special +	sla c +	rl b +; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if +; a Pokemon with 512 or more Defense has ued Reflect, or if a Pokemon with 512 or more Special has used Light Screen +.specialAttackCritCheck +	ld hl, wBattleMonSpecial +	ld a, [wCriticalHitOrOHKO] +	and a ; check for critical hit +	jr z, .scaleStats +; in the case of a critical hit, reset the player's and enemy's specials to their base values +	ld c, 5 ; special stat +	call GetEnemyMonStat +	ld a, [H_PRODUCT + 2] +	ld b, a +	ld a, [H_PRODUCT + 3] +	ld c, a +	push bc +	ld hl, wPartyMon1Special +	ld a, [wPlayerMonNumber] +	ld bc, wPartyMon2 - wPartyMon1 +	call AddNTimes +	pop bc +; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4 +; this allows values with up to 10 bits (values up to 1023) to be handled +; anything larger will wrap around +.scaleStats +	ld a, [hli] +	ld l, [hl] +	ld h, a ; hl = player's offensive stat +	or b ; is either high byte nonzero? +	jr z, .next ; if not, we don't need to scale +; bc /= 4 (scale enemy's defensive stat) +	srl b +	rr c +	srl b +	rr c +; defensive stat can actually end up as 0, leading to a division by 0 freeze during damage calculation +; hl /= 4 (scale player's offensive stat) +	srl h +	rr l +	srl h +	rr l +	ld a, l +	or h ; is the player's offensive stat 0? +	jr nz, .next +	inc l ; if the player's offensive stat is 0, bump it up to 1 +.next +	ld b, l ; b = player's offensive stat (possibly scaled) +	        ; (c already contains enemy's defensive stat (possibly scaled)) +	ld a, [wBattleMonLevel] +	ld e, a ; e = level +	ld a, [wCriticalHitOrOHKO] +	and a ; check for critical hit +	jr z, .done +	sla e ; double level if it was a critical hit +.done +	ld a, 1 +	and a +	ret + +; sets b, c, d, and e for the CalculateDamage routine in the case of an attack by the enemy mon +GetDamageVarsForEnemyAttack: ; 3dfe7 (f:5fe7) +	ld hl, wDamage ; damage to eventually inflict, initialise to zero +	xor a +	ld [hli], a +	ld [hl], a +	ld hl, wEnemyMovePower +	ld a, [hli] +	ld d, a ; d = move power +	and a +	ret z ; return if move power is zero +	ld a, [hl] ; a = [wEnemyMoveType] +	cp FIRE ; types >= FIRE are all special +	jr nc, .specialAttack +.physicalAttack +	ld hl, wBattleMonDefense +	ld a, [hli] +	ld b, a +	ld c, [hl] ; bc = player defense +	ld a, [wPlayerBattleStatus3] +	bit HasReflectUp, a ; check for Reflect +	jr z, .physicalAttackCritCheck +; if the player has used Reflect, double the player's defense +	sla c +	rl b +.physicalAttackCritCheck +	ld hl, wEnemyMonAttack +	ld a, [wCriticalHitOrOHKO] +	and a ; check for critical hit +	jr z, .scaleStats +; in the case of a critical hit, reset the player's defense and the enemy's attack to their base values +	ld hl, wPartyMon1Defense +	ld a, [wPlayerMonNumber] +	ld bc, wPartyMon2 - wPartyMon1 +	call AddNTimes +	ld a, [hli] +	ld b, a +	ld c, [hl] +	push bc +	ld c, 2 ; attack stat +	call GetEnemyMonStat +	ld hl, H_PRODUCT + 2 +	pop bc +	jr .scaleStats +.specialAttack +	ld hl, wBattleMonSpecial +	ld a, [hli] +	ld b, a +	ld c, [hl] +	ld a, [wPlayerBattleStatus3] +	bit HasLightScreenUp, a ; check for Light Screen +	jr z, .specialAttackCritCheck +; if the player has used Light Screen, double the player's special +	sla c +	rl b +; reflect and light screen boosts do not cap the stat at 999, so weird things will happen during stats scaling if +; a Pokemon with 512 or more Defense has ued Reflect, or if a Pokemon with 512 or more Special has used Light Screen +.specialAttackCritCheck +	ld hl, wEnemyMonSpecial +	ld a, [wCriticalHitOrOHKO] +	and a ; check for critical hit +	jr z, .scaleStats +; in the case of a critical hit, reset the player's and enemy's specials to their base values +	ld hl, wPartyMon1Special +	ld a, [wPlayerMonNumber] +	ld bc, wPartyMon2 - wPartyMon1 +	call AddNTimes +	ld a, [hli] +	ld b, a +	ld c, [hl] +	push bc +	ld c, 5 ; special stat +	call GetEnemyMonStat +	ld hl, H_PRODUCT + 2 +	pop bc +; if either the offensive or defensive stat is too large to store in a byte, scale both stats by dividing them by 4 +; this allows values with up to 10 bits (values up to 1023) to be handled +; anything larger will wrap around +.scaleStats +	ld a, [hli] +	ld l, [hl] +	ld h, a ; hl = enemy's offensive stat +	or b ; is either high byte nonzero? +	jr z, .next ; if not, we don't need to scale +; bc /= 4 (scale player's defensive stat) +	srl b +	rr c +	srl b +	rr c +; defensive stat can actually end up as 0, leading to a division by 0 freeze during damage calculation +; hl /= 4 (scale enemy's offensive stat) +	srl h +	rr l +	srl h +	rr l +	ld a, l +	or h ; is the enemy's offensive stat 0? +	jr nz, .next +	inc l ; if the enemy's offensive stat is 0, bump it up to 1 +.next +	ld b, l ; b = enemy's offensive stat (possibly scaled) +	        ; (c already contains player's defensive stat (possibly scaled)) +	ld a, [wEnemyMonLevel] +	ld e, a +	ld a, [wCriticalHitOrOHKO] +	and a ; check for critical hit +	jr z, .done +	sla e ; double level if it was a critical hit +.done +	ld a, $1 +	and a +	and a +	ret + +; get stat c of enemy mon +; c: stat to get (HP=1,Attack=2,Defense=3,Speed=4,Special=5) +GetEnemyMonStat: ; 3e08e (f:608e) +	push de +	push bc +	ld a, [wLinkState] +	cp LINK_STATE_BATTLING +	jr nz, .notLinkBattle +	ld hl, wEnemyMon1Stats +	dec c +	sla c +	ld b, $0 +	add hl, bc +	ld a, [wEnemyMonPartyPos] +	ld bc, wEnemyMon2 - wEnemyMon1 +	call AddNTimes +	ld a, [hli] +	ld [H_MULTIPLICAND + 1], a +	ld a, [hl] +	ld [H_MULTIPLICAND + 2], a +	pop bc +	pop de +	ret +.notLinkBattle +	ld a, [wEnemyMonLevel] +	ld [wCurEnemyLVL], a +	ld a, [wEnemyMonSpecies] +	ld [wd0b5], a +	call GetMonHeader +	ld hl, wEnemyMonDVs +	ld de, wLoadedMonSpeedExp +	ld a, [hli] +	ld [de], a +	inc de +	ld a, [hl] +	ld [de], a +	pop bc +	ld b, $0 +	ld hl, wLoadedMonSpeedExp - $b ; this base address makes CalcStat look in [wLoadedMonSpeedExp] for DVs +	call CalcStat +	pop de +	ret + +CalculateDamage: ; 3d0d7 (f:60d7) +; input: +;	b: attack +;	c: opponent defense +;	d: base power +;	e: level + +	ld a, [H_WHOSETURN] ; whose turn? +	and a +	ld a, [wPlayerMoveEffect] +	jr z, .effect +	ld a, [wEnemyMoveEffect] +.effect + +; EXPLODE_EFFECT halves defense. +	cp a, EXPLODE_EFFECT +	jr nz, .ok +	srl c +	jr nz, .ok +	inc c ; ...with a minimum value of 1 (used as a divisor later on) +.ok + +; Multi-hit attacks may or may not have 0 bp. +	cp a, TWO_TO_FIVE_ATTACKS_EFFECT +	jr z, .skipbp +	cp a, $1e +	jr z, .skipbp + +; Calculate OHKO damage based on remaining HP. +	cp a, OHKO_EFFECT +	jp z, JumpToOHKOMoveEffect + +; Don't calculate damage for moves that don't do any. +	ld a, d ; base power +	and a +	ret z +.skipbp + +	xor a +	ld hl, H_DIVIDEND +	ldi [hl], a +	ldi [hl], a +	ld [hl], a + +; Multiply level by 2 +	ld a, e ; level +	add a +	jr nc, .nc +	push af +	ld a, 1 +	ld [hl], a +	pop af +.nc +	inc hl +	ldi [hl], a + +; Divide by 5 +	ld a, 5 +	ldd [hl], a +	push bc +	ld b, 4 +	call Divide +	pop bc + +; Add 2 +	inc [hl] +	inc [hl] + +	inc hl ; multiplier + +; Multiply by attack base power +	ld [hl], d +	call Multiply + +; Multiply by attack stat +	ld [hl], b +	call Multiply + +; Divide by defender's defense stat +	ld [hl], c +	ld b, 4 +	call Divide + +; Divide by 50 +	ld [hl], 50 +	ld b, 4 +	call Divide + +	ld hl, wDamage +	ld b, [hl] +	ld a, [H_QUOTIENT + 3] +	add b +	ld [H_QUOTIENT + 3], a +	jr nc, .asm_3e142 + +	ld a, [H_QUOTIENT + 2] +	inc a +	ld [H_QUOTIENT + 2], a +	and a +	jr z, .asm_3e176 + +.asm_3e142 +	ld a, [H_QUOTIENT] +	ld b, a +	ld a, [H_QUOTIENT + 1] +	or a +	jr nz, .asm_3e176 + +	ld a, [H_QUOTIENT + 2] +	cp 998 / $100 +	jr c, .asm_3e15a +	cp 998 / $100 + 1 +	jr nc, .asm_3e176 +	ld a, [H_QUOTIENT + 3] +	cp 998 % $100 +	jr nc, .asm_3e176 + +.asm_3e15a +	inc hl +	ld a, [H_QUOTIENT + 3] +	ld b, [hl] +	add b +	ld [hld], a + +	ld a, [H_QUOTIENT + 2] +	ld b, [hl] +	adc b +	ld [hl], a +	jr c, .asm_3e176 + +	ld a, [hl] +	cp 998 / $100 +	jr c, .asm_3e17c +	cp 998 / $100 + 1 +	jr nc, .asm_3e176 +	inc hl +	ld a, [hld] +	cp 998 % $100 +	jr c, .asm_3e17c + +.asm_3e176 +; cap at 997 +	ld a, 997 / $100 +	ld [hli], a +	ld a, 997 % $100 +	ld [hld], a + +.asm_3e17c +; add 2 +	inc hl +	ld a, [hl] +	add 2 +	ld [hld], a +	jr nc, .done +	inc [hl] + +.done +; minimum damage is 1 +	ld a, 1 +	and a +	ret + +JumpToOHKOMoveEffect: ; 3e188 (f:6188) +	call JumpMoveEffect +	ld a, [wMoveMissed] +	dec a +	ret + + +UnusedHighCriticalMoves: ; 3e190 (f:6190) +	db KARATE_CHOP +	db RAZOR_LEAF +	db CRABHAMMER +	db SLASH +	db $FF +; 3e023 + +; determines if attack is a critical hit +; azure heights claims "the fastest pokémon (who are, not coincidentally, +; among the most popular) tend to CH about 20 to 25% of the time."  CriticalHitTest: ; 3e195 (f:6195) -	dr $3e195,$3e205 +	xor a +	ld [wCriticalHitOrOHKO], a +	ld a, [H_WHOSETURN] +	and a +	ld a, [wEnemyMonSpecies] +	jr nz, .handleEnemy +	ld a, [wBattleMonSpecies] +.handleEnemy +	ld [wd0b5], a +	call GetMonHeader +	ld a, [wMonHBaseSpeed] +	ld b, a +	srl b                        ; (effective (base speed/2)) +	ld a, [H_WHOSETURN] +	and a +	ld hl, wPlayerMovePower +	ld de, wPlayerBattleStatus2 +	jr z, .calcCriticalHitProbability +	ld hl, wEnemyMovePower +	ld de, wEnemyBattleStatus2 +.calcCriticalHitProbability +	ld a, [hld]                  ; read base power from RAM +	and a +	ret z                        ; do nothing if zero +	dec hl +	ld c, [hl]                   ; read move id +	ld a, [de] +	bit GettingPumped, a         ; test for focus energy +	jr nz, .focusEnergyUsed      ; bug: using focus energy causes a shift to the right instead of left, +	                             ; resulting in 1/4 the usual crit chance +	sla b                        ; (effective (base speed/2)*2) +	jr nc, .noFocusEnergyUsed +	ld b, $ff                    ; cap at 255/256 +	jr .noFocusEnergyUsed +.focusEnergyUsed +	srl b +.noFocusEnergyUsed +	ld hl, HighCriticalMoves     ; table of high critical hit moves +.Loop +	ld a, [hli]                  ; read move from move table +	cp c                         ; does it match the move about to be used? +	jr z, .HighCritical          ; if so, the move about to be used is a high critical hit ratio move +	inc a                        ; move on to the next move, FF terminates loop +	jr nz, .Loop                 ; check the next move in HighCriticalMoves +	srl b                        ; /2 for regular move (effective (base speed / 2)) +	jr .SkipHighCritical         ; continue as a normal move +.HighCritical +	sla b                        ; *2 for high critical hit moves +	jr nc, .noCarry +	ld b, $ff                    ; cap at 255/256 +.noCarry +	sla b                        ; *4 for high critical move (effective (base speed/2)*8)) +	jr nc, .SkipHighCritical +	ld b, $ff +.SkipHighCritical +	call BattleRandom            ; generates a random value, in "a" +	rlc a +	rlc a +	rlc a +	cp b                         ; check a against calculated crit rate +	ret nc                       ; no critical hit if no borrow +	ld a, $1 +	ld [wCriticalHitOrOHKO], a   ; set critical hit flag +	ret + +; high critical hit moves +HighCriticalMoves: ; 3e200 (f:6200) +	db KARATE_CHOP +	db RAZOR_LEAF +	db CRABHAMMER +	db SLASH +	db $FF + + +; function to determine if Counter hits and if so, how much damage it does  HandleCounterMove: ; 3e205 (f:6205) -	dr $3e205,$3e251 +; The variables checked by Counter are updated whenever the cursor points to a new move in the battle selection menu. +; This is irrelevant for the opponent's side outside of link battles, since the move selection is controlled by the AI. +; However, in the scenario where the player switches out and the opponent uses Counter, +; the outcome may be affected by the player's actions in the move selection menu prior to switching the Pokemon. +; This might also lead to desync glitches in link battles. + +	ld a,[H_WHOSETURN] ; whose turn +	and a +; player's turn +	ld hl,wEnemySelectedMove +	ld de,wEnemyMovePower +	ld a,[wPlayerSelectedMove] +	jr z,.next +; enemy's turn +	ld hl,wPlayerSelectedMove +	ld de,wPlayerMovePower +	ld a,[wEnemySelectedMove] +.next +	cp a,COUNTER +	ret nz ; return if not using Counter +	ld a,$01 +	ld [wMoveMissed],a ; initialize the move missed variable to true (it is set to false below if the move hits) +	ld a,[hl] +	cp a,COUNTER +	ret z ; miss if the opponent's last selected move is Counter. +	ld a,[de] +	and a +	ret z ; miss if the opponent's last selected move's Base Power is 0. +; check if the move the target last selected was Normal or Fighting type +	inc de +	ld a,[de] +	and a ; normal type +	jr z,.counterableType +	cp a,FIGHTING +	jr z,.counterableType +; if the move wasn't Normal or Fighting type, miss +	xor a +	ret +.counterableType +	ld hl,wDamage +	ld a,[hli] +	or [hl] +	ret z ; If we made it here, Counter still misses if the last move used in battle did no damage to its target. +	      ; wDamage is shared by both players, so Counter may strike back damage dealt by the Counter user itself +	      ; if the conditions meet, even though 99% of the times damage will come from the target. +; if it did damage, double it +	ld a,[hl] +	add a +	ldd [hl],a +	ld a,[hl] +	adc a +	ld [hl],a +	jr nc,.noCarry +; damage is capped at 0xFFFF +	ld a,$ff +	ld [hli],a +	ld [hl],a +.noCarry +	xor a +	ld [wMoveMissed],a +	call MoveHitTest ; do the normal move hit test in addition to Counter's special rules +	xor a +	ret +  ApplyAttackToEnemyPokemon: ; 3e251 (f:6251) -	dr $3e251,$3e2b4 +	ld a,[wPlayerMoveEffect] +	cp a,OHKO_EFFECT +	jr z,ApplyDamageToEnemyPokemon +	cp a,SUPER_FANG_EFFECT +	jr z,.superFangEffect +	cp a,SPECIAL_DAMAGE_EFFECT +	jr z,.specialDamage +	ld a,[wPlayerMovePower] +	and a +	jp z,ApplyAttackToEnemyPokemonDone ; no attack to apply if base power is 0 +	jr ApplyDamageToEnemyPokemon +.superFangEffect +; set the damage to half the target's HP +	ld hl,wEnemyMonHP +	ld de,wDamage +	ld a,[hli] +	srl a +	ld [de],a +	inc de +	ld b,a +	ld a,[hl] +	rr a +	ld [de],a +	or b +	jr nz,ApplyDamageToEnemyPokemon +; make sure Super Fang's damage is always at least 1 +	ld a,$01 +	ld [de],a +	jr ApplyDamageToEnemyPokemon +.specialDamage +	ld hl,wBattleMonLevel +	ld a,[hl] +	ld b,a ; Seismic Toss deals damage equal to the user's level +	ld a,[wPlayerMoveNum] +	cp a,SEISMIC_TOSS +	jr z,.storeDamage +	cp a,NIGHT_SHADE +	jr z,.storeDamage +	ld b,SONICBOOM_DAMAGE ; 20 +	cp a,SONICBOOM +	jr z,.storeDamage +	ld b,DRAGON_RAGE_DAMAGE ; 40 +	cp a,DRAGON_RAGE +	jr z,.storeDamage +; Psywave +	ld a,[hl] +	ld b,a +	srl a +	add b +	ld b,a ; b = level * 1.5 +; loop until a random number in the range [1, b) is found +.loop +	call BattleRandom +	and a +	jr z,.loop +	cp b +	jr nc,.loop +	ld b,a +.storeDamage ; store damage value at b +	ld hl,wDamage +	xor a +	ld [hli],a +	ld a,b +	ld [hl],a +  ApplyDamageToEnemyPokemon: ; 3e2b4 (f:62b4) -	dr $3e2b4,$3e372 +	ld hl,wDamage +	ld a,[hli] +	ld b,a +	ld a,[hl] +	or b +	jr z,ApplyAttackToEnemyPokemonDone ; we're done if damage is 0 +	ld a,[wEnemyBattleStatus2] +	bit HasSubstituteUp,a ; does the enemy have a substitute? +	jp nz,AttackSubstitute +; subtract the damage from the pokemon's current HP +; also, save the current HP at wHPBarOldHP +	ld a,[hld] +	ld b,a +	ld a,[wEnemyMonHP + 1] +	ld [wHPBarOldHP],a +	sub b +	ld [wEnemyMonHP + 1],a +	ld a,[hl] +	ld b,a +	ld a,[wEnemyMonHP] +	ld [wHPBarOldHP+1],a +	sbc b +	ld [wEnemyMonHP],a +	jr nc,.animateHpBar +; if more damage was done than the current HP, zero the HP and set the damage (wDamage) +; equal to how much HP the pokemon had before the attack +	ld a,[wHPBarOldHP+1] +	ld [hli],a +	ld a,[wHPBarOldHP] +	ld [hl],a +	xor a +	ld hl,wEnemyMonHP +	ld [hli],a +	ld [hl],a +.animateHpBar +	ld hl,wEnemyMonMaxHP +	ld a,[hli] +	ld [wHPBarMaxHP+1],a +	ld a,[hl] +	ld [wHPBarMaxHP],a +	ld hl,wEnemyMonHP +	ld a,[hli] +	ld [wHPBarNewHP+1],a +	ld a,[hl] +	ld [wHPBarNewHP],a +	coord hl, 2, 2 +	xor a +	ld [wHPBarType],a +	predef UpdateHPBar2 ; animate the HP bar shortening +ApplyAttackToEnemyPokemonDone: ; 3e30f (f:630f) +	jp DrawHUDsAndHPBars + +ApplyAttackToPlayerPokemon: ; 3e312 (f:6312) +	ld a,[wEnemyMoveEffect] +	cp a,OHKO_EFFECT +	jr z,ApplyDamageToPlayerPokemon +	cp a,SUPER_FANG_EFFECT +	jr z,.superFangEffect +	cp a,SPECIAL_DAMAGE_EFFECT +	jr z,.specialDamage +	ld a,[wEnemyMovePower] +	and a +	jp z,ApplyAttackToPlayerPokemonDone +	jr ApplyDamageToPlayerPokemon +.superFangEffect +; set the damage to half the target's HP +	ld hl,wBattleMonHP +	ld de,wDamage +	ld a,[hli] +	srl a +	ld [de],a +	inc de +	ld b,a +	ld a,[hl] +	rr a +	ld [de],a +	or b +	jr nz,ApplyDamageToPlayerPokemon +; make sure Super Fang's damage is always at least 1 +	ld a,$01 +	ld [de],a +	jr ApplyDamageToPlayerPokemon +.specialDamage +	ld hl,wEnemyMonLevel +	ld a,[hl] +	ld b,a +	ld a,[wEnemyMoveNum] +	cp a,SEISMIC_TOSS +	jr z,.storeDamage +	cp a,NIGHT_SHADE +	jr z,.storeDamage +	ld b,SONICBOOM_DAMAGE +	cp a,SONICBOOM +	jr z,.storeDamage +	ld b,DRAGON_RAGE_DAMAGE +	cp a,DRAGON_RAGE +	jr z,.storeDamage +; Psywave +	ld a,[hl] +	ld b,a +	srl a +	add b +	ld b,a ; b = attacker's level * 1.5 +; loop until a random number in the range [0, b) is found +; this differs from the range when the player attacks, which is [1, b) +; it's possible for the enemy to do 0 damage with Psywave, but the player always does at least 1 damage +.loop +	call BattleRandom +	cp b +	jr nc,.loop +	ld b,a +.storeDamage +	ld hl,wDamage +	xor a +	ld [hli],a +	ld a,b +	ld [hl],a +  ApplyDamageToPlayerPokemon: ; 3e372 (f:6372) -	dr $3e372,$3e428 +	ld hl,wDamage +	ld a,[hli] +	ld b,a +	ld a,[hl] +	or b +	jr z,ApplyAttackToPlayerPokemonDone ; we're done if damage is 0 +	ld a,[wPlayerBattleStatus2] +	bit HasSubstituteUp,a ; does the player have a substitute? +	jp nz,AttackSubstitute +; subtract the damage from the pokemon's current HP +; also, save the current HP at wHPBarOldHP and the new HP at wHPBarNewHP +	ld a,[hld] +	ld b,a +	ld a,[wBattleMonHP + 1] +	ld [wHPBarOldHP],a +	sub b +	ld [wBattleMonHP + 1],a +	ld [wHPBarNewHP],a +	ld b,[hl] +	ld a,[wBattleMonHP] +	ld [wHPBarOldHP+1],a +	sbc b +	ld [wBattleMonHP],a +	ld [wHPBarNewHP+1],a +	jr nc,.animateHpBar +; if more damage was done than the current HP, zero the HP and set the damage (wDamage) +; equal to how much HP the pokemon had before the attack +	ld a,[wHPBarOldHP+1] +	ld [hli],a +	ld a,[wHPBarOldHP] +	ld [hl],a +	xor a +	ld hl,wBattleMonHP +	ld [hli],a +	ld [hl],a +	ld hl,wHPBarNewHP +	ld [hli],a +	ld [hl],a +.animateHpBar +	ld hl,wBattleMonMaxHP +	ld a,[hli] +	ld [wHPBarMaxHP+1],a +	ld a,[hl] +	ld [wHPBarMaxHP],a +	coord hl, 10, 9 +	ld a,$01 +	ld [wHPBarType],a +	predef UpdateHPBar2 ; animate the HP bar shortening +ApplyAttackToPlayerPokemonDone: ; 3e3cd (f:63cd) +	jp DrawHUDsAndHPBars + +AttackSubstitute: ; 3e3d0 (f:63d0) +; 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. + +	ld hl,SubstituteTookDamageText +	call PrintText +; values for player turn +	ld de,wEnemySubstituteHP +	ld bc,wEnemyBattleStatus2 +	ld a,[H_WHOSETURN] +	and a +	jr z,.applyDamageToSubstitute +; values for enemy turn +	ld de,wPlayerSubstituteHP +	ld bc,wPlayerBattleStatus2 +.applyDamageToSubstitute +	ld hl,wDamage +	ld a,[hli] +	and a +	jr nz,.substituteBroke ; damage > 0xFF always breaks substitutes +; subtract damage from HP of substitute +	ld a,[de] +	sub [hl] +	ld [de],a +	ret nc +.substituteBroke +; If the target's Substitute breaks, wDamage isn't updated with the amount of HP +; the Substitute had before being attacked. +	ld h,b +	ld l,c +	res HasSubstituteUp,[hl] ; unset the substitute bit +	ld hl,SubstituteBrokeText +	call PrintText +; flip whose turn it is for the next function call +	ld a,[H_WHOSETURN] +	xor a,$01 +	ld [H_WHOSETURN],a +	callab Func_79929 ; animate the substitute breaking +; flip the turn back to the way it was +	ld a,[H_WHOSETURN] +	xor a,$01 +	ld [H_WHOSETURN],a +	ld hl,wPlayerMoveEffect ; value for player's turn +	and a +	jr z,.nullifyEffect +	ld hl,wEnemyMoveEffect ; value for enemy's turn +.nullifyEffect +	xor a +	ld [hl],a ; zero the effect of the attacker's move +	jp DrawHUDsAndHPBars + +SubstituteTookDamageText: ; 3e41e (f:641e) +	TX_FAR _SubstituteTookDamageText +	db "@" + +SubstituteBrokeText: ; 3e423 (f:6423) +	TX_FAR _SubstituteBrokeText +	db "@" + +; this function raises the attack modifier of a pokemon using Rage when that pokemon is attacked  HandleBuildingRage: ; 3e428 (f:6428) -	dr $3e428,$3e46f +; values for the player turn +	ld hl,wEnemyBattleStatus2 +	ld de,wEnemyMonStatMods +	ld bc,wEnemyMoveNum +	ld a,[H_WHOSETURN] +	and a +	jr z,.next +; values for the enemy turn +	ld hl,wPlayerBattleStatus2 +	ld de,wPlayerMonStatMods +	ld bc,wPlayerMoveNum +.next +	bit UsingRage,[hl] ; is the pokemon being attacked under the effect of Rage? +	ret z ; return if not +	ld a,[de] +	cp a,$0d ; maximum stat modifier value +	ret z ; return if attack modifier is already maxed +	ld a,[H_WHOSETURN] +	xor a,$01 ; flip turn for the stat modifier raising function +	ld [H_WHOSETURN],a +; temporarily change the target pokemon's move to $00 and the effect to the one +; that causes the attack modifier to go up one stage +	ld h,b +	ld l,c +	ld [hl],$00 ; null move number +	inc hl +	ld [hl],ATTACK_UP1_EFFECT +	push hl +	ld hl,BuildingRageText +	call PrintText +	call StatModifierUpEffect ; stat modifier raising function +	pop hl +	xor a +	ldd [hl],a ; null move effect +	ld a,RAGE +	ld [hl],a ; restore the target pokemon's move number to Rage +	ld a,[H_WHOSETURN] +	xor a,$01 ; flip turn back to the way it was +	ld [H_WHOSETURN],a +	ret + +BuildingRageText: ; 3e46a (f:646a) +	TX_FAR _BuildingRageText +	db "@" + +; copy last move for Mirror Move +; sets zero flag on failure and unsets zero flag on success  MirrorMoveCopyMove: ; 3e46f (f:646f) -	dr $3e46f,$3e4ba +; Mirror Move makes use of ccf1 (wPlayerUsedMove) and ccf2 (wEnemyUsedMove) addresses, +; which are mainly used to print the "[Pokemon] used [Move]" text. +; Both are set to 0 whenever a new Pokemon is sent out +; ccf1 is also set to 0 whenever the player is fast asleep or frozen solid. +; ccf2 is also set to 0 whenever the enemy is fast asleep or frozen solid. + +	ld a,[H_WHOSETURN] +	and a +; values for player turn +	ld a,[wEnemyUsedMove] +	ld hl,wPlayerSelectedMove +	ld de,wPlayerMoveNum +	jr z,.next +; values for enemy turn +	ld a,[wPlayerUsedMove] +	ld de,wEnemyMoveNum +	ld hl,wEnemySelectedMove +.next +	ld [hl],a +	cp a,MIRROR_MOVE ; did the target Pokemon last use Mirror Move, and miss? +	jr z,.mirrorMoveFailed +	and a ; has the target selected any move yet? +	jr nz,ReloadMoveData +.mirrorMoveFailed +	ld hl,MirrorMoveFailedText +	call PrintText +	xor a +	ret + +MirrorMoveFailedText: ; 3e496 (f:6496) +	TX_FAR _MirrorMoveFailedText +	db "@" + +; function used to reload move data for moves like Mirror Move and Metronome +ReloadMoveData: ; 3e49b (f:649b) +	ld [wd11e],a +	dec a +	ld hl,Moves +	ld bc,MoveEnd - Moves +	call AddNTimes +	ld a,BANK(Moves) +	call FarCopyData ; copy the move's stats +	call IncrementMovePP +; the follow two function calls are used to reload the move name +	call GetMoveName +	call CopyStringToCF4B +	ld a,$01 +	and a +	ret + +; function that picks a random move for metronome  MetronomePickMove: ; 3e4ba (f:64ba) -	dr $3e4ba,$3e517 +	xor a +	ld [wAnimationType],a +	ld a,METRONOME +	call PlayMoveAnimation ; play Metronome's animation +; values for player turn +	ld de,wPlayerMoveNum +	ld hl,wPlayerSelectedMove +	ld a,[H_WHOSETURN] +	and a +	jr z,.pickMoveLoop +; values for enemy turn +	ld de,wEnemyMoveNum +	ld hl,wEnemySelectedMove +; loop to pick a random number in the range [1, $a5) to be the move used by Metronome +.pickMoveLoop +	call BattleRandom +	and a +	jr z,.pickMoveLoop +	cp a,NUM_ATTACKS + 1 ; max normal move number + 1 (this is Struggle's move number) +	jr nc,.pickMoveLoop +	cp a,METRONOME +	jr z,.pickMoveLoop +	ld [hl],a +	jr ReloadMoveData + +; this function increments the current move's PP +; it's used to prevent moves that run another move within the same turn +; (like Mirror Move and Metronome) from losing 2 PP +IncrementMovePP: ; 3e4e5 (f:64e5) +	ld a,[H_WHOSETURN] +	and a +; values for player turn +	ld hl,wBattleMonPP +	ld de,wPartyMon1PP +	ld a,[wPlayerMoveListIndex] +	jr z,.next +; values for enemy turn +	ld hl,wEnemyMonPP +	ld de,wEnemyMon1PP +	ld a,[wEnemyMoveListIndex] +.next +	ld b,$00 +	ld c,a +	add hl,bc +	inc [hl] ; increment PP in the currently battling pokemon memory location +	ld h,d +	ld l,e +	add hl,bc +	ld a,[H_WHOSETURN] +	and a +	ld a,[wPlayerMonNumber] ; value for player turn +	jr z,.updatePP +	ld a,[wEnemyMonPartyPos] ; value for enemy turn +.updatePP +	ld bc,wEnemyMon2 - wEnemyMon1 +	call AddNTimes +	inc [hl] ; increment PP in the party memory location +	ret + +; function to adjust the base damage of an attack to account for type effectiveness  AdjustDamageForMoveType: ; 3e517 (f:6517) -	dr $3e517,$3e5bb +; values for player turn +	ld hl,wBattleMonType +	ld a,[hli] +	ld b,a    ; b = type 1 of attacker +	ld c,[hl] ; c = type 2 of attacker +	ld hl,wEnemyMonType +	ld a,[hli] +	ld d,a    ; d = type 1 of defender +	ld e,[hl] ; e = type 2 of defender +	ld a,[wPlayerMoveType] +	ld [wMoveType],a +	ld a,[H_WHOSETURN] +	and a +	jr z,.next +; values for enemy turn +	ld hl,wEnemyMonType +	ld a,[hli] +	ld b,a    ; b = type 1 of attacker +	ld c,[hl] ; c = type 2 of attacker +	ld hl,wBattleMonType +	ld a,[hli] +	ld d,a    ; d = type 1 of defender +	ld e,[hl] ; e = type 2 of defender +	ld a,[wEnemyMoveType] +	ld [wMoveType],a +.next +	ld a,[wMoveType] +	cp b ; does the move type match type 1 of the attacker? +	jr z,.sameTypeAttackBonus +	cp c ; does the move type match type 2 of the attacker? +	jr z,.sameTypeAttackBonus +	jr .skipSameTypeAttackBonus +.sameTypeAttackBonus +; if the move type matches one of the attacker's types +	ld hl,wDamage + 1 +	ld a,[hld] +	ld h,[hl] +	ld l,a    ; hl = damage +	ld b,h +	ld c,l    ; bc = damage +	srl b +	rr c      ; bc = floor(0.5 * damage) +	add hl,bc ; hl = floor(1.5 * damage) +; store damage +	ld a,h +	ld [wDamage],a +	ld a,l +	ld [wDamage + 1],a +	ld hl,wDamageMultipliers +	set 7,[hl] +.skipSameTypeAttackBonus +	ld a,[wMoveType] +	ld b,a +	ld hl,TypeEffects +.loop +	ld a,[hli] ; a = "attacking type" of the current type pair +	cp a,$ff +	jr z,.done +	cp b ; does move type match "attacking type"? +	jr nz,.nextTypePair +	ld a,[hl] ; a = "defending type" of the current type pair +	cp d ; does type 1 of defender match "defending type"? +	jr z,.matchingPairFound +	cp e ; does type 2 of defender match "defending type"? +	jr z,.matchingPairFound +	jr .nextTypePair +.matchingPairFound +; if the move type matches the "attacking type" and one of the defender's types matches the "defending type" +	push hl +	push bc +	inc hl +	ld a,[wDamageMultipliers] +	and a,$80 +	ld b,a +	ld a,[hl] ; a = damage multiplier +	ld [H_MULTIPLIER],a +	add b +	ld [wDamageMultipliers],a +	xor a +	ld [H_MULTIPLICAND],a +	ld hl,wDamage +	ld a,[hli] +	ld [H_MULTIPLICAND + 1],a +	ld a,[hld] +	ld [H_MULTIPLICAND + 2],a +	call Multiply +	ld a,10 +	ld [H_DIVISOR],a +	ld b,$04 +	call Divide +	ld a,[H_QUOTIENT + 2] +	ld [hli],a +	ld b,a +	ld a,[H_QUOTIENT + 3] +	ld [hl],a +	or b ; is damage 0? +	jr nz,.skipTypeImmunity +.typeImmunity +; if damage is 0, make the move miss +; this only occurs if a move that would do 2 or 3 damage is 0.25x effective against the target +	inc a +	ld [wMoveMissed],a +.skipTypeImmunity +	pop bc +	pop hl +.nextTypePair +	inc hl +	inc hl +	jp .loop +.done +	ret  AIGetTypeEffectiveness: ; 3e5bb (f:65bb)  	ld a,[wEnemyMoveType] diff --git a/engine/battle/moveEffects/heal_effect.asm b/engine/battle/moveEffects/heal_effect.asm index 7a1983d7..418f7df7 100644 --- a/engine/battle/moveEffects/heal_effect.asm +++ b/engine/battle/moveEffects/heal_effect.asm @@ -3,7 +3,7 @@ HealEffect_: ; f62ba (3d:62ba)  	and a  	ld de, wBattleMonHP  	ld hl, wBattleMonMaxHP -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	jr z, .healEffect  	ld de, wEnemyMonHP  	ld hl, wEnemyMonMaxHP diff --git a/engine/battle/moveEffects/paralyze_effect.asm b/engine/battle/moveEffects/paralyze_effect.asm index a8d39629..5cec6b02 100644 --- a/engine/battle/moveEffects/paralyze_effect.asm +++ b/engine/battle/moveEffects/paralyze_effect.asm @@ -1,6 +1,6 @@  ParalyzeEffect_: ; f6562 (3d:6562)  	ld hl, wEnemyMonStatus -	ld de, W_PLAYERMOVETYPE +	ld de, wPlayerMoveType  	ld a, [H_WHOSETURN]  	and a  	jp z, .next diff --git a/engine/battle/moveEffects/recoil_effect.asm b/engine/battle/moveEffects/recoil_effect.asm index 984feba7..d65696e2 100644 --- a/engine/battle/moveEffects/recoil_effect.asm +++ b/engine/battle/moveEffects/recoil_effect.asm @@ -1,7 +1,7 @@  RecoilEffect_: ; 138f6 (4:78f6)  	ld a, [H_WHOSETURN]  	and a -	ld a, [W_PLAYERMOVENUM] +	ld a, [wPlayerMoveNum]  	ld hl, wBattleMonMaxHP  	jr z, .recoilEffect  	ld a, [wEnemyMoveNum] diff --git a/engine/battle/print_type.asm b/engine/battle/print_type.asm index b90f5682..7b581905 100644 --- a/engine/battle/print_type.asm +++ b/engine/battle/print_type.asm @@ -34,7 +34,7 @@ EraseType2Text: ; 27d41 (9:7d41)  PrintMoveType: ; 27d4d (9:7d4d)  	call GetPredefRegisters  	push hl -	ld a, [W_PLAYERMOVETYPE] +	ld a, [wPlayerMoveType]  ; fall through  PrintType_: ; 27d54 (9:7d54) diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm index cc7e93db..6b6247c9 100644 --- a/engine/battle/trainer_ai.asm +++ b/engine/battle/trainer_ai.asm @@ -126,7 +126,7 @@ AIMoveChoiceModification1: ; 3972e (e:572e)  	ret z ; no more moves in move set  	inc de  	call ReadMove -	ld a, [W_ENEMYMOVEPOWER] +	ld a, [wEnemyMovePower]  	and a  	jr nz, .nextMove  	ld a, [wEnemyMoveEffect] @@ -240,7 +240,7 @@ AIMoveChoiceModification3: ; 3979a (e:579a)  	ld a, [wEnemyMoveType]  	cp d  	jr z, .loopMoves -	ld a, [W_ENEMYMOVEPOWER] +	ld a, [wEnemyMovePower]  	and a  	jr nz, .betterMoveFound ; damaging moves of a different type are considered to be better moves  	jr .loopMoves diff --git a/engine/items/items.asm b/engine/items/items.asm index 8a21de7c..e3e8eace 100755 --- a/engine/items/items.asm +++ b/engine/items/items.asm @@ -1693,9 +1693,9 @@ ItemUseXStat: ; df69 (3:df69)  	ld [wActionResultOrTookBattleTurn],a ; item not used  	ret  .inBattle -	ld hl,W_PLAYERMOVENUM +	ld hl,wPlayerMoveNum  	ld a,[hli] -	push af ; save [W_PLAYERMOVENUM] +	push af ; save [wPlayerMoveNum]  	ld a,[hl]  	push af ; save [wPlayerMoveEffect]  	push hl @@ -1704,7 +1704,7 @@ ItemUseXStat: ; df69 (3:df69)  	ld [hl],a ; store player move effect  	call PrintItemUseTextAndRemoveItem  	ld a,XSTATITEM_ANIM ; X stat item animation ID -	ld [W_PLAYERMOVENUM],a +	ld [wPlayerMoveNum],a  	call LoadScreenTilesFromBuffer1 ; restore saved screen  	call Delay3  	xor a @@ -1723,7 +1723,7 @@ ItemUseXStat: ; df69 (3:df69)  	pop af  	ld [hld],a ; restore [wPlayerMoveEffect]  	pop af -	ld [hl],a ; restore [W_PLAYERMOVENUM] +	ld [hl],a ; restore [wPlayerMoveNum]  	ret  ItemUsePokeflute: ; dfbd (3:5fbd) @@ -1490,7 +1490,7 @@ wEnemyMoveNum:: ; cfcc  	ds 1  wEnemyMoveEffect:: ; cfcd  	ds 1 -W_ENEMYMOVEPOWER:: ; cfce +wEnemyMovePower:: ; cfce  	ds 1  wEnemyMoveType:: ; cfcf  	ds 1 @@ -1498,13 +1498,13 @@ W_ENEMYMOVEACCURACY:: ; cfd0  	ds 1  W_ENEMYMOVEMAXPP:: ; cfd1  	ds 1 -W_PLAYERMOVENUM:: ; cfd2 +wPlayerMoveNum:: ; cfd2  	ds 1  wPlayerMoveEffect:: ; cfd3  	ds 1 -W_PLAYERMOVEPOWER:: ; cfd4 +wPlayerMovePower:: ; cfd4  	ds 1 -W_PLAYERMOVETYPE:: ; cfd5 +wPlayerMoveType:: ; cfd5  	ds 1  W_PLAYERMOVEACCURACY:: ; cfd6  	ds 1 diff --git a/yellow/main.asm b/yellow/main.asm index ccdb4240..f87b4ac7 100755 --- a/yellow/main.asm +++ b/yellow/main.asm @@ -4225,7 +4225,9 @@ ReshowSubstituteAnim: ; 798b2 (1e:58b2)  AnimationTransformMon: ; 798c8 (1e:58c8)  	dr $798c8,$798d4  ChangeMonPic: ; 798d4 (1e:58d4) -	dr $798d4,$7a037 +	dr $798d4,$79929 +Func_79929: ; 79929 (1e:5929) +	dr $79929,$7a037  AnimCut: ; 7a037 (1e:6037)  	dr $7a037,$7a0fb  AnimateBoulderDust: ; 7a0fb (1e:60fb) | 
