shithub: pokered

Download patch

ref: 9c3684535a646d47e3173e0d2291338d03bdb94e
parent: 187642e9051b000e5ad3d6de84697410c7022869
author: YamaArashi <shadow962@live.com>
date: Tue Jan 24 05:13:58 EST 2012

more battle code disassembled

hg-commit-id: b7c80c2263e2


--- a/common.asm
+++ b/common.asm
@@ -25241,22 +25241,315 @@
 	db $50
 ; 0x3e2b1 + 5 bytes
 
-INCBIN "baserom.gbc",$3e2b6,$3e2f8 - $3e2b6
+; this function raises the attack modifier of a pokemon using Rage when that pokemon is attacked
+HandleBuildingRage: ; 62B6
+; values for the player turn
+	ld hl,W_ENEMYBATTSTATUS2
+	ld de,W_ENEMYMONATTACKMOD
+	ld bc,W_ENEMYMOVENUM
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.next\@
+; values for the enemy turn
+	ld hl,W_PLAYERBATTSTATUS2
+	ld de,W_PLAYERMONATTACKMOD
+	ld bc,W_PLAYERMOVENUM
+.next\@
+	bit 6,[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
+; 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 $7428 ; 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
 
-UnnamedText_3e2f8: ; 0x3e2f8
-	TX_FAR _UnnamedText_3e2f8
+BuildingRageText: ; 0x3e2f8
+	TX_FAR _BuildingRageText
 	db $50
 ; 0x3e2f8 + 5 bytes
 
-INCBIN "baserom.gbc",$3e2fd,$3e324 - $3e2fd
+; copy last move for Mirror Move
+; sets zero flag on failure and unsets zero flag on success
+MirrorMoveCopyMove: ; 62FD
+	ld a,[H_WHOSETURN]
+	and a
+; values for player turn
+	ld a,[$ccf2]
+	ld hl,W_PLAYERSELECTEDMOVE
+	ld de,W_PLAYERMOVENUM
+	jr z,.next\@
+; values for enemy turn
+	ld a,[$ccf1]
+	ld de,W_ENEMYMOVENUM
+	ld hl,W_ENEMYSELECTEDMOVE
+.next\@
+	ld [hl],a
+	cp a,MIRROR_MOVE ; did the target pokemon also use Mirror Move?
+	jr z,.mirrorMoveFailed\@
+	and a ; null move?
+	jr nz,ReloadMoveData
+.mirrorMoveFailed\@
+; Mirror Move fails on itself and null moves
+	ld hl,MirrorMoveFailedText
+	call PrintText
+	xor a
+	ret
 
-UnnamedText_3e324: ; 0x3e324
-	TX_FAR _UnnamedText_3e324
+MirrorMoveFailedText: ; 0x3e324
+	TX_FAR _MirrorMoveFailedText
 	db $50
 ; 0x3e324 + 5 bytes
 
-INCBIN "baserom.gbc",$3e329,$14b
+; function used to reload move data for moves like Mirror Move and Metronome
+ReloadMoveData: ; 6329
+	ld [$d11e],a
+	dec a
+	ld hl,Moves
+	ld bc,$0006
+	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 $3058
+	call $3826
+	ld a,$01
+	and a
+	ret
 
+; function that picks a random move for metronome
+MetronomePickMove: ; 6348
+	xor a
+	ld [$cc5b],a
+	ld a,METRONOME
+	call PlayMoveAnimation ; play Metronome's animation
+; values for player turn
+	ld de,W_PLAYERMOVENUM
+	ld hl,W_PLAYERSELECTEDMOVE
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.pickMoveLoop\@
+; values for enemy turn
+	ld de,W_ENEMYMOVENUM
+	ld hl,W_ENEMYSELECTEDMOVE
+; loop to pick a random number in the range [1, $a5) to be the move used by Metronome
+.pickMoveLoop\@
+	call $6e9b ; random number
+	and a
+	jr z,.pickMoveLoop\@
+	cp a,$a5 ; 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: ; 6373
+	ld a,[H_WHOSETURN]
+	and a
+; values for player turn
+	ld hl,W_PLAYERMONPP
+	ld de,W_PARTYMON1_MOVE1PP
+	ld a,[W_PLAYERMOVELISTINDEX]
+	jr z,.next\@
+; values for enemy turn
+	ld hl,W_ENEMYMONPP
+	ld de,$d8c1 ; enemy party pokemon 1 PP
+	ld a,[W_ENEMYMOVELISTINDEX]
+.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,[W_PLAYERMONNUMBER] ; value for player turn
+	jr z,.next2\@
+	ld a,[W_ENEMYMONNUMBER] ; value for enemy turn
+.next2\@
+	ld bc,$002c
+	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: ; 63A5
+; values for player turn
+	ld hl,W_PLAYERMONTYPES
+	ld a,[hli]
+	ld b,a    ; b = type 1 of attacker
+	ld c,[hl] ; c = type 2 of attacker
+	ld hl,W_ENEMYMONTYPES
+	ld a,[hli]
+	ld d,a    ; d = type 1 of defender
+	ld e,[hl] ; e = type 2 of defender
+	ld a,[W_PLAYERMOVETYPE]
+	ld [$d11e],a
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.next\@
+; values for enemy turn
+	ld hl,W_ENEMYMONTYPES
+	ld a,[hli]
+	ld b,a    ; b = type 1 of attacker
+	ld c,[hl] ; c = type 2 of attacker
+	ld hl,W_PLAYERMONTYPES
+	ld a,[hli]
+	ld d,a    ; d = type 1 of defender
+	ld e,[hl] ; e = type 2 of defender
+	ld a,[W_ENEMYMOVETYPE]
+	ld [$d11e],a
+.next\@
+	ld a,[$d11e] ; move type
+	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,W_DAMAGE + 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 [W_DAMAGE],a
+	ld a,l
+	ld [W_DAMAGE + 1],a
+	ld hl,$d05b
+	set 7,[hl]
+.skipSameTypeAttackBonus\@
+	ld a,[$d11e]
+	ld b,a ; b = move type
+	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,[$d05b]
+	and a,$80
+	ld b,a
+	ld a,[hl] ; a = damage multiplier
+	ld [$ff99],a
+	add b
+	ld [$d05b],a
+	xor a
+	ld [$ff96],a
+	ld hl,W_DAMAGE
+	ld a,[hli]
+	ld [$ff97],a
+	ld a,[hld]
+	ld [$ff98],a
+	call $38ac ; multiply
+	ld a,10
+	ld [$ff99],a
+	ld b,$04
+	call $38b9 ; divide
+	ld a,[$ff97]
+	ld [hli],a
+	ld b,a
+	ld a,[$ff98]
+	ld [hl],a
+	or b ; is damage 0?
+	jr nz,.skipTypeImmunity\@
+.typeImmunity\@
+; if damage is 0, make the move miss
+	inc a
+	ld [W_MOVEMISSED],a
+.skipTypeImmunity\@
+	pop bc
+	pop hl
+.nextTypePair\@
+	inc hl
+	inc hl
+	jp .loop\@
+.done\@
+	ret
+
+; function to tell how effective the type of an enemy attack is on the player's current pokemon
+; this doesn't take into account the effects that dual types can have
+; (e.g. 4x weakness / resistance, weaknesses and resistances canceling)
+; the result is stored in [$D11E]
+; ($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: ; 6449
+	ld a,[W_ENEMYMOVETYPE]
+	ld d,a                 ; d = type of enemy move
+	ld hl,W_PLAYERMONTYPES
+	ld b,[hl]              ; b = type 1 of player's pokemon
+	inc hl
+	ld c,[hl]              ; c = type 2 of player's pokemon
+	ld a,$10
+	ld [$d11e],a           ; initialize [$D11E] to neutral effectiveness
+	ld hl,TypeEffects
+.loop\@
+	ld a,[hli]
+	cp a,$ff
+	ret z
+	cp d                   ; match the type of the move
+	jr nz,.nextTypePair1\@
+	ld a,[hli]
+	cp b                   ; match with type 1 of pokemon
+	jr z,.done\@
+	cp c                   ; or match with type 2 of pokemon
+	jr z,.done\@
+	jr .nextTypePair2\@
+.nextTypePair1\@
+	inc hl
+.nextTypePair2\@
+	inc hl
+	jr .loop\@
+.done\@
+	ld a,[hl]
+	ld [$d11e],a           ; store damage multiplier
+	ret
+
 TypeEffects: ; 6474
 ; format: attacking type, defending type, damage multiplier
 ; the multiplier is a (decimal) fixed-point number:
@@ -57070,12 +57363,12 @@
 	db "SUBSTITUTE broke!", $58
 ; 0x89b6a + 22 bytes
 
-_UnnamedText_3e2f8: ; 0x89b80
+_BuildingRageText: ; 0x89b80
 	db $0, $5a, "'s", $4f
 	db "RAGE is building!", $58
 ; 0x89b80 + 22 bytes
 
-_UnnamedText_3e324: ; 0x89b96
+_MirrorMoveFailedText: ; 0x89b96
 	db $0, "The MIRROR MOVE", $4e, "failed!", $58
 ; 0x89b96 + 25 bytes
 
--- a/constants.asm
+++ b/constants.asm
@@ -89,6 +89,9 @@
 
 ; wram locations
 
+W_PLAYERMOVELISTINDEX EQU $CC2E
+W_PLAYERMONNUMBER EQU $CC2F
+
 ; current HP of player and enemy substitutes
 W_PLAYERSUBSITUTEHP EQU $CCD7
 W_ENEMYSUBSITUTEHP EQU $CCD8
@@ -96,6 +99,8 @@
 W_PLAYERSELECTEDMOVE EQU $CCDC
 W_ENEMYSELECTEDMOVE  EQU $CCDD
 
+W_ENEMYMOVELISTINDEX EQU $CCE2
+
 W_AICOUNT EQU $CCDF ; number of times remaining that AI action can occur
 
 ; stat modifiers for the player's current pokemon
@@ -150,8 +155,12 @@
 	; bit 5 frz
 	; bit 6 par
 	; unused? (XXX confirm)
+W_ENEMYMONTYPES EQU $CFEA
+W_ENEMYMONTYPE1 EQU $CFEA
+W_ENEMYMONTYPE2 EQU $CFEB
 W_ENEMYMONLEVEL EQU $CFF3
 W_ENEMYMONMAXHP EQU $CFF4 ; (16 bits)
+W_ENEMYMONPP    EQU $CFFE
 
 W_PLAYERMONCURHP EQU $D015 ; active opponent's hp (16 bits)
 W_PLAYERMONSTATUS EQU $D018 ; the status of the player’s current monster
@@ -163,8 +172,12 @@
 	; bit 5 frz
 	; bit 6 par
 	; unused? (XXX confirm)
+W_PLAYERMONTYPES EQU $D019
+W_PLAYERMONTYPE1 EQU $D019
+W_PLAYERMONTYPE2 EQU $D01A
 W_PLAYERMONLEVEL EQU $D022
 W_PLAYERMONMAXHP EQU $D023 ; (16 bits)
+W_PLAYERMONPP    EQU $D02D
 
 W_TRAINERCLASS EQU $D031