shithub: pokered

Download patch

ref: cf0d22fa2eee87ba6349e35ce153dfe511cbc130
parent: 79c24d9c93e1e07b20e35a4d1cd87fa845861d3c
parent: 187642e9051b000e5ad3d6de84697410c7022869
author: Bryan Bishop <[email protected]>
date: Tue Jan 24 07:11:56 EST 2012

merge YamaArashi/pokered

hg-commit-id: a3767c66df56


--- a/common.asm
+++ b/common.asm
@@ -24942,15 +24942,71 @@
 	db $FF
 ; 0x3e093
 
-INCBIN "baserom.gbc",$3e093,$3e0df - $3e093
+; function to determine if Counter hits and if so, how much damage it does
+HandleCounterMove: ; 6093
+	ld a,[H_WHOSETURN] ; whose turn
+	and a
+; player's turn
+	ld hl,W_ENEMYSELECTEDMOVE
+	ld de,W_ENEMYMOVEPOWER
+	ld a,[W_PLAYERSELECTEDMOVE]
+	jr z,.next\@
+; enemy's turn
+	ld hl,W_PLAYERSELECTEDMOVE
+	ld de,W_PLAYERMOVEPOWER
+	ld a,[W_ENEMYSELECTEDMOVE]
+.next\@
+	cp a,COUNTER
+	ret nz ; return if not using Counter
+	ld a,$01
+	ld [W_MOVEMISSED],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 ; if the target also used Counter, miss
+	ld a,[de]
+	and a
+	ret z ; if the move the target used has 0 power, miss
+; check if the move the target used 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,W_DAMAGE
+	ld a,[hli]
+	or [hl]
+	ret z ; Counter misses if the target did no damage to the Counter user
+; double the damage that the target did to the Counter user
+	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 [W_MOVEMISSED],a
+	call MoveHitTest ; do the normal move hit test in addition to Counter's special rules
+	xor a
+	ret
 
 ApplyDamageToEnemyPokemon: ; 60DF
 	ld a,[W_PLAYERMOVEEFFECT]
-	cp a,$26 ; OHKO
+	cp a,OHKO_EFFECT
 	jr z,.applyDamage\@
-	cp a,$28 ; super fang's effect
+	cp a,SUPER_FANG_EFFECT
 	jr z,.superFangEffect\@
-	cp a,$29 ; special damage (fixed or random damage)
+	cp a,SPECIAL_DAMAGE_EFFECT
 	jr z,.specialDamage\@
 	ld a,[W_PLAYERMOVEPOWER]
 	and a
@@ -24983,10 +25039,10 @@
 	jr z,.storeDamage\@
 	cp a,NIGHT_SHADE
 	jr z,.storeDamage\@
-	ld b,$14 ; Sonic Boom damage
+	ld b,SONICBOOM_DAMAGE
 	cp a,SONICBOOM
 	jr z,.storeDamage\@
-	ld b,$28 ; Dragon Rage damage
+	ld b,DRAGON_RAGE_DAMAGE
 	cp a,DRAGON_RAGE
 	jr z,.storeDamage\@
 ; Psywave
@@ -24995,7 +25051,7 @@
 	srl a
 	add b
 	ld b,a ; b = level * 1.5
-; loop until a random number between 1 and b is found
+; loop until a random number in the range [1, b) is found
 .loop\@
 	call $6e9b ; random number
 	and a
@@ -25018,7 +25074,7 @@
 	jr z,.done\@ ; we're done if damage is 0
 	ld a,[W_ENEMYBATTSTATUS2]
 	bit 4,a ; does the enemy have a substitute?
-	jp nz,$625e
+	jp nz,AttackSubstitute
 ; subtract the damage from the pokemon's current HP
 ; also, save the current HP at $CEEB
 	ld a,[hld]
@@ -25035,7 +25091,7 @@
 	ld [W_ENEMYMONCURHP],a
 	jr nc,.animateHpBar\@
 ; if more damage was done than the current HP, zero the HP and set the damage
-; equal to how much HP the pokemon had before fainting
+; equal to how much HP the pokemon had before the attack
 	ld a,[$ceec]
 	ld [hli],a
 	ld a,[$ceeb]
@@ -25063,15 +25119,179 @@
 .done\@
 	jp $4d5a ; redraw pokemon names and HP bars
 
-INCBIN "baserom.gbc",$3e1a0,$3e2ac - $3e1a0
+ApplyDamageToPlayerPokemon: ; 61A0
+	ld a,[W_ENEMYMOVEEFFECT]
+	cp a,OHKO_EFFECT
+	jr z,.applyDamage\@
+	cp a,SUPER_FANG_EFFECT
+	jr z,.superFangEffect\@
+	cp a,SPECIAL_DAMAGE_EFFECT
+	jr z,.specialDamage\@
+	ld a,[W_ENEMYMOVEPOWER]
+	and a
+	jp z,.done\@
+	jr .applyDamage\@
+.superFangEffect\@
+; set the damage to half the target's HP
+	ld hl,W_PLAYERMONCURHP
+	ld de,W_DAMAGE
+	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,.applyDamage\@
+; make sure Super Fang's damage is always at least 1
+	ld a,$01
+	ld [de],a
+	jr .applyDamage\@
+.specialDamage\@
+	ld hl,W_ENEMYMONLEVEL
+	ld a,[hl]
+	ld b,a
+	ld a,[W_ENEMYMOVENUM]
+	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 $6e9b ; random number
+	cp b
+	jr nc,.loop\@
+	ld b,a
+.storeDamage\@
+	ld hl,W_DAMAGE
+	xor a
+	ld [hli],a
+	ld a,b
+	ld [hl],a
+.applyDamage\@
+	ld hl,W_DAMAGE
+	ld a,[hli]
+	ld b,a
+	ld a,[hl]
+	or b
+	jr z,.done\@ ; we're done if damage is 0
+	ld a,[W_PLAYERBATTSTATUS2]
+	bit 4,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 $CEEB and the new HP at $CEED
+	ld a,[hld]
+	ld b,a
+	ld a,[W_PLAYERMONCURHP + 1]
+	ld [$ceeb],a
+	sub b
+	ld [W_PLAYERMONCURHP + 1],a
+	ld [$ceed],a
+	ld b,[hl]
+	ld a,[W_PLAYERMONCURHP]
+	ld [$ceec],a
+	sbc b
+	ld [W_PLAYERMONCURHP],a
+	ld [$ceee],a
+	jr nc,.animateHpBar\@
+; if more damage was done than the current HP, zero the HP and set the damage
+; equal to how much HP the pokemon had before the attack
+	ld a,[$ceec]
+	ld [hli],a
+	ld a,[$ceeb]
+	ld [hl],a
+	xor a
+	ld hl,W_PLAYERMONCURHP
+	ld [hli],a
+	ld [hl],a
+	ld hl,$ceed
+	ld [hli],a
+	ld [hl],a
+.animateHpBar\@
+	ld hl,W_PLAYERMONMAXHP
+	ld a,[hli]
+	ld [$ceea],a
+	ld a,[hl]
+	ld [$cee9],a
+	ld hl,$c45e
+	ld a,$01
+	ld [$cf94],a
+	ld a,$48
+	call Predef ; animate the HP bar shortening
+.done\@
+	jp $4d5a ; redraw pokemon names and HP bars
 
-UnnamedText_3e2ac: ; 0x3e2ac
-	TX_FAR _UnnamedText_3e2ac
+AttackSubstitute: ; 625E
+	ld hl,SubstituteTookDamageText
+	call PrintText
+; values for player turn
+	ld de,W_ENEMYSUBSITUTEHP
+	ld bc,W_ENEMYBATTSTATUS2
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.applyDamageToSubstitute\@
+; values for enemy turn
+	ld de,W_PLAYERSUBSITUTEHP
+	ld bc,W_PLAYERBATTSTATUS2
+.applyDamageToSubstitute\@
+	ld hl,W_DAMAGE
+	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\@
+	ld h,b
+	ld l,c
+	res 4,[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
+	ld hl,$5747
+	ld b,$1e ; animate the substitute breaking
+	call Bankswitch ; substitute
+; flip the turn back to the way it was
+	ld a,[H_WHOSETURN]
+	xor a,$01
+	ld [H_WHOSETURN],a
+	ld hl,W_PLAYERMOVEEFFECT ; value for player's turn
+	and a
+	jr z,.nullifyEffect\@
+	ld hl,W_ENEMYMOVEEFFECT ; value for enemy's turn
+.nullifyEffect\@
+	xor a
+	ld [hl],a ; zero the effect of the attacker's move
+	jp $4d5a ; redraw pokemon names and HP bars
+
+SubstituteTookDamageText: ; 0x3e2ac
+	TX_FAR _SubstituteTookDamageText
 	db $50
 ; 0x3e2ac + 5 bytes
 
-UnnamedText_3e2b1: ; 0x3e2b1
-	TX_FAR _UnnamedText_3e2b1
+SubstituteBrokeText: ; 0x3e2b1
+	TX_FAR _SubstituteBrokeText
 	db $50
 ; 0x3e2b1 + 5 bytes
 
@@ -25181,8 +25401,198 @@
 	db DRAGON,DRAGON,20
 	db $FF
 
-INCBIN "baserom.gbc",$3e56b,$3e887 - $3e56b
+; some tests that need to pass for a move to hit
+MoveHitTest: ; 656B
+; player's turn
+	ld hl,W_ENEMYBATTSTATUS1
+	ld de,W_PLAYERMOVEEFFECT
+	ld bc,W_ENEMYMONSTATUS
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.dreamEaterCheck\@
+; enemy's turn
+	ld hl,W_PLAYERBATTSTATUS1
+	ld de,W_ENEMYMOVEEFFECT
+	ld bc,W_PLAYERMONSTATUS
+.dreamEaterCheck\@
+	ld a,[de]
+	cp a,DREAM_EATER_EFFECT
+	jr nz,.swiftCheck\@
+	ld a,[bc]
+	and a,$07 ; is the target pokemon sleeping?
+	jp z,.moveMissed\@
+.swiftCheck\@
+	ld a,[de]
+	cp a,SWIFT_EFFECT
+	ret z ; Swift never misses (interestingly, Azure Heights lists this is a myth, but it appears to be true)
+	call $7b79 ; substitute check (note that this overwrites a)
+	jr z,.checkForDigOrFlyStatus\@
+; this code is buggy. it's supposed to prevent HP draining moves from working on substitutes.
+; since $7b79 overwrites a with either $00 or $01, it never works.
+	cp a,DRAIN_HP_EFFECT ; $03
+	jp z,.moveMissed\@
+	cp a,DREAM_EATER_EFFECT ; $08
+	jp z,.moveMissed\@
+.checkForDigOrFlyStatus\@
+	bit 6,[hl]
+	jp nz,.moveMissed\@
+	ld a,[H_WHOSETURN]
+	and a
+	jr nz,.enemyTurn\@
+.playerTurn\@
+; this checks if the move effect is disallowed by mist
+	ld a,[W_PLAYERMOVEEFFECT]
+	cp a,$12
+	jr c,.skipEnemyMistCheck\@
+	cp a,$1a
+	jr c,.enemyMistCheck\@
+	cp a,$3a
+	jr c,.skipEnemyMistCheck\@
+	cp a,$42
+	jr c,.enemyMistCheck\@
+	jr .skipEnemyMistCheck\@
+.enemyMistCheck\@
+; if move effect is from $12 to $19 inclusive or $3a to $41 inclusive
+; i.e. the following moves
+; GROWL, TAIL WHIP, LEER, STRING SHOT, SAND-ATTACK, SMOKESCREEN, KINESIS,
+; FLASH, CONVERSION, HAZE*, SCREECH, LIGHT SCREEN*, REFLECT*
+; the moves that are marked with an asterisk are not affected since this
+; function is not called when those moves are used
+; XXX are there are any others like those three?
+	ld a,[W_ENEMYBATTSTATUS2]
+	bit 1,a
+	jp nz,.moveMissed\@
+.skipEnemyMistCheck\@
+	ld a,[W_PLAYERBATTSTATUS2]
+	bit 0,a ; is the player using X Accuracy?
+	ret nz ; if so, always hit regardless of accuracy/evasion
+	jr .calcHitChance\@
+.enemyTurn\@
+	ld a,[W_ENEMYMOVEEFFECT]
+	cp a,$12
+	jr c,.skipPlayerMistCheck\@
+	cp a,$1a
+	jr c,.playerMistCheck\@
+	cp a,$3a
+	jr c,.skipPlayerMistCheck\@
+	cp a,$42
+	jr c,.playerMistCheck\@
+	jr .skipPlayerMistCheck\@
+.playerMistCheck\@
+; similar to enemy mist check
+	ld a,[W_PLAYERBATTSTATUS2]
+	bit 1,a
+	jp nz,.moveMissed\@
+.skipPlayerMistCheck\@
+	ld a,[W_ENEMYBATTSTATUS2]
+	bit 0,a ; is the enemy using X Accuracy?
+	ret nz ; if so, always hit regardless of accuracy/evasion
+.calcHitChance\@
+	call CalcHitChance ; scale the move accuracy according to attacker's accuracy and target's evasion
+	ld a,[W_PLAYERMOVEACCURACY]
+	ld b,a
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.doAccuracyCheck\@
+	ld a,[W_ENEMYMOVEACCURACY]
+	ld b,a
+.doAccuracyCheck\@
+; if the random number generated is greater than or equal to the scaled accuracy, the move misses
+; note that this means that even the highest accuracy is still just a 255/256 chance, not 100%
+	call $6e9b ; random number
+	cp b
+	jr nc,.moveMissed\@
+	ret
+.moveMissed\@
+	xor a
+	ld hl,W_DAMAGE ; zero the damage
+	ld [hli],a
+	ld [hl],a
+	inc a
+	ld [W_MOVEMISSED],a
+	ld a,[H_WHOSETURN]
+	and a
+	jr z,.playerTurn2\@
+.enemyTurn2\@
+	ld hl,W_ENEMYBATTSTATUS1
+	res 5,[hl] ; end multi-turn attack e.g. wrap
+	ret
+.playerTurn2\@
+	ld hl,W_PLAYERBATTSTATUS1
+	res 5,[hl] ; end multi-turn attack e.g. wrap
+	ret
 
+; values for player turn
+CalcHitChance: ; 6624
+	ld hl,W_PLAYERMOVEACCURACY
+	ld a,[H_WHOSETURN]
+	and a
+	ld a,[W_PLAYERMONACCURACYMOD]
+	ld b,a
+	ld a,[W_ENEMYMONEVASIONMOD]
+	ld c,a
+	jr z,.next\@
+; values for enemy turn
+	ld hl,W_ENEMYMOVEACCURACY
+	ld a,[W_ENEMYMONACCURACYMOD]
+	ld b,a
+	ld a,[W_PLAYERMONEVASIONMOD]
+	ld c,a
+.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)
+; zero the high bytes of the multiplicand
+	xor a
+	ld [$ff96],a
+	ld [$ff97],a
+	ld a,[hl]
+	ld [$ff98],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\@
+	push bc
+	ld hl,$76cb ; stat modifier ratios
+	dec b
+	sla b
+	ld c,b
+	ld b,$00
+	add hl,bc ; hl = address of stat modifier ratio
+	pop bc
+	ld a,[hli]
+	ld [$ff99],a ; set multiplier to the numerator of the ratio
+	call $38ac ; multiply
+	ld a,[hl]
+	ld [$ff99],a ; set divisor to the the denominator of the ratio (the dividend is the product of the previous multiplication)
+	ld b,$04 ; number of significant bytes in the dividend
+	call $38b9 ; divide
+	ld a,[$ff98]
+	ld b,a
+	ld a,[$ff97]
+	or b
+	jp nz,.nextCalculation\@
+; make sure the result is always at least one
+	ld [$ff97],a
+	ld a,$01
+	ld [$ff98],a
+.nextCalculation\@
+	ld b,c
+	dec d
+	jr nz,.loop\@
+	ld a,[$ff97]
+	and a ; is the calculated hit chance over 0xFF?
+	ld a,[$ff98]
+	jr z,.storeAccuracy\@
+; if calculated hit chance over 0xFF
+	ld a,$ff ; set the hit chance to 0xFF
+.storeAccuracy\@
+	pop hl
+	ld [hl],a ; store the hit chance in the move accuracy variable
+	ret
+
+INCBIN "baserom.gbc",$3e687,$3e887 - $3e687
+
 UnnamedText_3e887: ; 0x3e887
 	TX_FAR _UnnamedText_3e887
 	db $50
@@ -56703,13 +57113,13 @@
 	db "ignored orders!", $58
 ; 0x89b32 + 21 bytes
 
-_UnnamedText_3e2ac: ; 0x89b47
+_SubstituteTookDamageText: ; 0x89b47
 	db $0, "The SUBSTITUTE", $4f
 	db "took damage for", $55
 	db $59, "!", $58
 ; 0x89b47 + 35 bytes
 
-_UnnamedText_3e2b1: ; 0x89b6a
+_SubstituteBrokeText: ; 0x89b6a
 	db $0, $59, "'s", $4f
 	db "SUBSTITUTE broke!", $58
 ; 0x89b6a + 22 bytes
--- a/constants.asm
+++ b/constants.asm
@@ -89,11 +89,36 @@
 
 ; wram locations
 
+; current HP of player and enemy substitutes
+W_PLAYERSUBSITUTEHP EQU $CCD7
+W_ENEMYSUBSITUTEHP EQU $CCD8
+
 W_PLAYERSELECTEDMOVE EQU $CCDC
 W_ENEMYSELECTEDMOVE  EQU $CCDD
 
 W_AICOUNT EQU $CCDF ; number of times remaining that AI action can occur
 
+; stat modifiers for the player's current pokemon
+; value can range from 1 - 13 ($1 to $D)
+; 7 is normal
+
+W_PLAYERMONATTACKMOD   EQU $CD1A
+W_PLAYERMONDEFENSEMOD  EQU $CD1B
+W_PLAYERMONSPEEDMOD    EQU $CD1C
+W_PLAYERMONSPECIALMOD  EQU $CD1D
+W_PLAYERMONACCURACYMOD EQU $CD1E
+W_PLAYERMONEVASIONMOD  EQU $CD1F
+
+; stat modifiers for the enemy's current pokemon
+; value can range from 1 - 13 ($1 to $D)
+; 7 is normal
+W_ENEMYMONATTACKMOD   EQU $CD2E
+W_ENEMYMONDEFENSEMOD  EQU $CD2F
+W_ENEMYMONSPEEDMOD    EQU $CD30
+W_ENEMYMONSPECIALMOD  EQU $CD31
+W_ENEMYMONACCURACYMOD EQU $CD32
+W_ENEMYMONEVASIONMOD  EQU $CD33
+
 W_WHICHTRADE EQU $CD3D ; which entry from TradeMons to select
 
 W_WHICHPOKEMON EQU $CF92 ; which pokemon you selected
@@ -1172,6 +1197,81 @@
 TM_49         EQU $F9
 TM_50         EQU $FA
 
+; tentative move effect constants
+; {stat}_(UP|DOWN)(1|2) means that the move raises the user's (or lowers the target's) corresponding stat modifier by 1 (or 2) stages
+; {status condition}_side_effect means that the move has a side chance of causing that condition
+; {status condition}_effect means that the move causes the status condition every time it hits the target
+POISON_SIDE_EFFECT1        EQU $02
+DRAIN_HP_EFFECT            EQU $03
+BURN_SIDE_EFFECT1          EQU $04
+FREEZE_SIDE_EFFECT         EQU $05
+PARALYZE_SIDE_EFFECT1      EQU $06
+EXPLODE_EFFECT             EQU $07 ; Explosion, Self Destruct
+DREAM_EATER_EFFECT         EQU $08
+MIRROR_MOVE_EFFECT         EQU $09
+ATTACK_UP1_EFFECT          EQU $0A
+DEFENSE_UP1_EFFECT         EQU $0B
+SPECIAL_UP1_EFFECT         EQU $0D
+EVASION_UP1_EFFECT         EQU $0F
+PAY_DAY_EFFECT             EQU $10
+SWIFT_EFFECT               EQU $11
+ATTACK_DOWN1_EFFECT        EQU $12
+DEFENSE_DOWN1_EFFECT       EQU $13
+SPEED_DOWN1_EFFECT         EQU $14
+ACCURACY_DOWN1_EFFECT      EQU $16
+CONVERSION_EFFECT          EQU $18
+HAZE_EFFECT                EQU $19
+BIDE_EFFECT                EQU $1A
+THRASH_PETAL_DANCE_EFFECT  EQU $1B
+SWITCH_AND_TELEPORT_EFFECT EQU $1C
+TWO_TO_FIVE_ATTACKS_EFFECT EQU $1D
+FLINCH_SIDE_EFFECT1        EQU $1F
+SLEEP_EFFECT               EQU $20
+POISON_SIDE_EFFECT2        EQU $21
+BURN_SIDE_EFFECT2          EQU $22
+PARALYZE_SIDE_EFFECT2      EQU $24
+FLINCH_SIDE_EFFECT2        EQU $25
+OHKO_EFFECT                EQU $26 ; moves like Horn Drill
+CHARGE_EFFECT              EQU $27 ; moves like Solar Beam
+SUPER_FANG_EFFECT          EQU $28
+SPECIAL_DAMAGE_EFFECT      EQU $29 ; Seismic Toss, Night Shade, Sonic Boom, Dragon Rage, Psywave
+TRAPPING_EFFECT            EQU $2A ; moves like Wrap
+FLY_EFFECT                 EQU $2B
+ATTACK_TWICE_EFFECT        EQU $2C
+JUMP_KICK_EFFECT           EQU $2D ; Jump Kick and Hi Jump Kick effect
+MIST_EFFECT                EQU $2E
+FOCUS_ENERGY_EFFECT        EQU $2F
+RECOIL_EFFECT              EQU $30 ; moves like Double Edge
+CONFUSION_EFFECT           EQU $31 ; Confuse Ray, Supersonic (not the move Confusion)
+ATTACK_UP2_EFFECT          EQU $32
+DEFENSE_UP2_EFFECT         EQU $33
+SPEED_UP2_EFFECT           EQU $34
+SPECIAL_UP2_EFFECT         EQU $35
+HEAL_EFFECT                EQU $38 ; Recover, Softboiled, Rest
+TRANSFORM_EFFECT           EQU $39
+DEFENSE_DOWN2_EFFECT       EQU $3B
+LIGHT_SCREEN_EFFECT        EQU $40
+REFLECT_EFFECT             EQU $41
+POISON_EFFECT              EQU $42
+PARALYZE_EFFECT            EQU $43
+ATTACK_DOWN_SIDE_EFFECT    EQU $44
+DEFENSE_DOWN_SIDE_EFFECT   EQU $45
+SPEED_DOWN_SIDE_EFFECT     EQU $46
+SPECIAL_DOWN_SIDE_EFFECT   EQU $47
+CONFUSION_SIDE_EFFECT      EQU $4C
+TWINEEDLE_EFFECT           EQU $4D
+SUBSTITUTE_EFFECT          EQU $4F
+HYPER_BEAM_EFFECT          EQU $50
+RAGE_EFFECT                EQU $51
+MIMIC_EFFECT               EQU $52
+METRONOME_EFFECT           EQU $53
+LEECH_SEED_EFFECT          EQU $54
+SPLASH_EFFECT              EQU $55
+DISABLE_EFFECT             EQU $56
+
+; fixed damage constants
+SONICBOOM_DAMAGE   EQU 20
+DRAGON_RAGE_DAMAGE EQU 40
 
 ; move name constants
 POUND        EQU $01