diff options
author | entrpntr <entrpntr@gmail.com> | 2020-04-19 12:31:56 -0400 |
---|---|---|
committer | entrpntr <entrpntr@gmail.com> | 2020-04-19 12:31:56 -0400 |
commit | e953302d3f81f080fd5d8423000496ce2fad36d3 (patch) | |
tree | bb66787122ec1029524153c96c3f34b66780e5c7 | |
parent | e10598eb204358343491c92348b9220185e3b33d (diff) |
Continue with effect commands (about 50% complete).
47 files changed, 3673 insertions, 109 deletions
diff --git a/constants/battle_constants.asm b/constants/battle_constants.asm index 2c5e6b83..4fc3020b 100644 --- a/constants/battle_constants.asm +++ b/constants/battle_constants.asm @@ -66,6 +66,8 @@ NUM_BATTLE_STATS EQU NUM_STATS - 1 ; don't count HP STAT_MIN_NORMAL EQU 5 STAT_MIN_HP EQU 10 +MAX_STAT_VALUE EQU 999 + ; shiny dvs ATKDEFDV_SHINY EQU $EA SPDSPCDV_SHINY EQU $AA diff --git a/constants/type_constants.asm b/constants/type_constants.asm index b7b350e3..3fb9649a 100644 --- a/constants/type_constants.asm +++ b/constants/type_constants.asm @@ -1,3 +1,9 @@ +; TypeNames indexes (see data/types/names.asm) +; also used in: +; - PokedexTypeSearchConversionTable (see data/types/search_types.asm) +; - PokedexTypeSearchStrings (see data/types/search_strings.asm) +; - TypeMatchups (see data/types/type_matchups.asm) +; - TypeBoostItems (see data/types/type_boost_items.asm) const_def PHYSICAL EQU const_value @@ -22,7 +28,7 @@ UNUSED_TYPES EQU const_value const TYPE_16 const TYPE_17 const TYPE_18 - const CURSE_T + const CURSE_TYPE UNUSED_TYPES_END EQU const_value SPECIAL EQU const_value @@ -30,9 +36,10 @@ SPECIAL EQU const_value const WATER const GRASS const ELECTRIC - const PSYCHIC + const PSYCHIC_TYPE const ICE const DRAGON const DARK - TYPES_END EQU const_value + +NUM_TYPES EQU TYPES_END + UNUSED_TYPES - UNUSED_TYPES_END diff --git a/data/battle/accuracy_multipliers.asm b/data/battle/accuracy_multipliers.asm new file mode 100644 index 00000000..4b52a090 --- /dev/null +++ b/data/battle/accuracy_multipliers.asm @@ -0,0 +1,17 @@ +; Multiplier ratios for accuracy from modifier -6 to +6 +; (for other stats, see data/battle/stat_multipliers.asm). + +AccuracyLevelMultipliers: + db 33, 100 ; -6 = 33% + db 36, 100 ; -5 = 36% + db 43, 100 ; -4 = 43% + db 50, 100 ; -3 = 50% + db 60, 100 ; -2 = 60% + db 75, 100 ; -1 = 75% + db 1, 1 ; 0 = 100% + db 133, 100 ; +1 = 133% + db 166, 100 ; +2 = 166% + db 2, 1 ; +3 = 200% + db 233, 100 ; +4 = 233% + db 133, 50 ; +5 = 266% + db 3, 1 ; +6 = 300% diff --git a/data/moves/flail_reversal_power.asm b/data/moves/flail_reversal_power.asm new file mode 100644 index 00000000..fb915905 --- /dev/null +++ b/data/moves/flail_reversal_power.asm @@ -0,0 +1,8 @@ +FlailReversalPower: + ; hp bar pixels, power + db HP_BAR_LENGTH_PX / 48, 200 + db HP_BAR_LENGTH_PX / 12, 150 + db HP_BAR_LENGTH_PX / 5, 100 + db HP_BAR_LENGTH_PX / 3, 80 + db HP_BAR_LENGTH_PX * 2 / 3, 40 + db HP_BAR_LENGTH_PX, 20 diff --git a/data/pokemon/base_stats/abra.asm b/data/pokemon/base_stats/abra.asm index e43adeec..d5073235 100644 --- a/data/pokemon/base_stats/abra.asm +++ b/data/pokemon/base_stats/abra.asm @@ -3,7 +3,7 @@ db 25, 20, 15, 90, 105, 55 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 200 ; catch rate db 73 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/alakazam.asm b/data/pokemon/base_stats/alakazam.asm index 6524400b..673ae050 100644 --- a/data/pokemon/base_stats/alakazam.asm +++ b/data/pokemon/base_stats/alakazam.asm @@ -3,7 +3,7 @@ db 55, 50, 45, 120, 135, 85 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 50 ; catch rate db 186 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/celebi.asm b/data/pokemon/base_stats/celebi.asm index 49cb349d..cef8879f 100644 --- a/data/pokemon/base_stats/celebi.asm +++ b/data/pokemon/base_stats/celebi.asm @@ -3,7 +3,7 @@ db 100, 100, 100, 100, 100, 100 ; hp atk def spd sat sdf - db PSYCHIC, GRASS ; type + db PSYCHIC_TYPE, GRASS ; type db 45 ; catch rate db 64 ; base exp db NO_ITEM, MIRACLEBERRY ; items diff --git a/data/pokemon/base_stats/drowzee.asm b/data/pokemon/base_stats/drowzee.asm index 614dd3d8..f6865872 100644 --- a/data/pokemon/base_stats/drowzee.asm +++ b/data/pokemon/base_stats/drowzee.asm @@ -3,7 +3,7 @@ db 60, 48, 45, 42, 43, 90 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 190 ; catch rate db 102 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/espeon.asm b/data/pokemon/base_stats/espeon.asm index 7913fc16..44126640 100644 --- a/data/pokemon/base_stats/espeon.asm +++ b/data/pokemon/base_stats/espeon.asm @@ -3,7 +3,7 @@ db 65, 65, 60, 110, 130, 95 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 45 ; catch rate db 197 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/exeggcute.asm b/data/pokemon/base_stats/exeggcute.asm index 6aad891f..8ec4ac50 100644 --- a/data/pokemon/base_stats/exeggcute.asm +++ b/data/pokemon/base_stats/exeggcute.asm @@ -3,7 +3,7 @@ db 60, 40, 80, 40, 60, 45 ; hp atk def spd sat sdf - db GRASS, PSYCHIC ; type + db GRASS, PSYCHIC_TYPE ; type db 90 ; catch rate db 98 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/exeggutor.asm b/data/pokemon/base_stats/exeggutor.asm index f67ecf4a..7a217259 100644 --- a/data/pokemon/base_stats/exeggutor.asm +++ b/data/pokemon/base_stats/exeggutor.asm @@ -3,7 +3,7 @@ db 95, 95, 85, 55, 125, 65 ; hp atk def spd sat sdf - db GRASS, PSYCHIC ; type + db GRASS, PSYCHIC_TYPE ; type db 45 ; catch rate db 212 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/girafarig.asm b/data/pokemon/base_stats/girafarig.asm index 93acd159..015b46ad 100644 --- a/data/pokemon/base_stats/girafarig.asm +++ b/data/pokemon/base_stats/girafarig.asm @@ -3,7 +3,7 @@ db 70, 80, 65, 85, 90, 65 ; hp atk def spd sat sdf - db NORMAL, PSYCHIC ; type + db NORMAL, PSYCHIC_TYPE ; type db 60 ; catch rate db 149 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/hypno.asm b/data/pokemon/base_stats/hypno.asm index f19dd638..8490a106 100644 --- a/data/pokemon/base_stats/hypno.asm +++ b/data/pokemon/base_stats/hypno.asm @@ -3,7 +3,7 @@ db 85, 73, 70, 67, 73, 115 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 75 ; catch rate db 165 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/jynx.asm b/data/pokemon/base_stats/jynx.asm index 3e43e23b..6563aa28 100644 --- a/data/pokemon/base_stats/jynx.asm +++ b/data/pokemon/base_stats/jynx.asm @@ -3,7 +3,7 @@ db 65, 50, 35, 95, 115, 95 ; hp atk def spd sat sdf - db ICE, PSYCHIC ; type + db ICE, PSYCHIC_TYPE ; type db 45 ; catch rate db 137 ; base exp db ICE_BERRY, ICE_BERRY ; items diff --git a/data/pokemon/base_stats/kadabra.asm b/data/pokemon/base_stats/kadabra.asm index da2f3bf4..48a34dde 100644 --- a/data/pokemon/base_stats/kadabra.asm +++ b/data/pokemon/base_stats/kadabra.asm @@ -3,7 +3,7 @@ db 40, 35, 30, 105, 120, 70 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 100 ; catch rate db 145 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/lugia.asm b/data/pokemon/base_stats/lugia.asm index 9fa2a759..f29ccc33 100644 --- a/data/pokemon/base_stats/lugia.asm +++ b/data/pokemon/base_stats/lugia.asm @@ -3,7 +3,7 @@ db 106, 90, 130, 110, 90, 154 ; hp atk def spd sat sdf - db PSYCHIC, FLYING ; type + db PSYCHIC_TYPE, FLYING ; type db 3 ; catch rate db 220 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/mew.asm b/data/pokemon/base_stats/mew.asm index c910fa66..6236dc88 100644 --- a/data/pokemon/base_stats/mew.asm +++ b/data/pokemon/base_stats/mew.asm @@ -3,7 +3,7 @@ db 100, 100, 100, 100, 100, 100 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 45 ; catch rate db 64 ; base exp db NO_ITEM, MIRACLEBERRY ; items diff --git a/data/pokemon/base_stats/mewtwo.asm b/data/pokemon/base_stats/mewtwo.asm index 39f1fdbf..66a7bd72 100644 --- a/data/pokemon/base_stats/mewtwo.asm +++ b/data/pokemon/base_stats/mewtwo.asm @@ -3,7 +3,7 @@ db 106, 110, 90, 130, 154, 90 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 3 ; catch rate db 220 ; base exp db NO_ITEM, BERSERK_GENE ; items diff --git a/data/pokemon/base_stats/mr__mime.asm b/data/pokemon/base_stats/mr__mime.asm index 5d7d2bad..f690cec6 100644 --- a/data/pokemon/base_stats/mr__mime.asm +++ b/data/pokemon/base_stats/mr__mime.asm @@ -3,7 +3,7 @@ db 40, 45, 65, 90, 100, 120 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 45 ; catch rate db 136 ; base exp db NO_ITEM, MYSTERYBERRY ; items diff --git a/data/pokemon/base_stats/natu.asm b/data/pokemon/base_stats/natu.asm index 4eaa2677..e4906ab9 100644 --- a/data/pokemon/base_stats/natu.asm +++ b/data/pokemon/base_stats/natu.asm @@ -3,7 +3,7 @@ db 40, 50, 45, 70, 70, 45 ; hp atk def spd sat sdf - db PSYCHIC, FLYING ; type + db PSYCHIC_TYPE, FLYING ; type db 190 ; catch rate db 73 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/slowbro.asm b/data/pokemon/base_stats/slowbro.asm index 2e256b36..ffe95d6c 100644 --- a/data/pokemon/base_stats/slowbro.asm +++ b/data/pokemon/base_stats/slowbro.asm @@ -3,7 +3,7 @@ db 95, 75, 110, 30, 100, 80 ; hp atk def spd sat sdf - db WATER, PSYCHIC ; type + db WATER, PSYCHIC_TYPE ; type db 75 ; catch rate db 164 ; base exp db NO_ITEM, KINGS_ROCK ; items diff --git a/data/pokemon/base_stats/slowking.asm b/data/pokemon/base_stats/slowking.asm index 0c870f4a..d7e9b4af 100644 --- a/data/pokemon/base_stats/slowking.asm +++ b/data/pokemon/base_stats/slowking.asm @@ -3,7 +3,7 @@ db 95, 75, 80, 30, 100, 110 ; hp atk def spd sat sdf - db WATER, PSYCHIC ; type + db WATER, PSYCHIC_TYPE ; type db 70 ; catch rate db 164 ; base exp db NO_ITEM, KINGS_ROCK ; items diff --git a/data/pokemon/base_stats/slowpoke.asm b/data/pokemon/base_stats/slowpoke.asm index e8c718b8..cc06c5b0 100644 --- a/data/pokemon/base_stats/slowpoke.asm +++ b/data/pokemon/base_stats/slowpoke.asm @@ -3,7 +3,7 @@ db 90, 65, 65, 15, 40, 40 ; hp atk def spd sat sdf - db WATER, PSYCHIC ; type + db WATER, PSYCHIC_TYPE ; type db 190 ; catch rate db 99 ; base exp db NO_ITEM, KINGS_ROCK ; items diff --git a/data/pokemon/base_stats/smoochum.asm b/data/pokemon/base_stats/smoochum.asm index d8670632..548ad5f5 100644 --- a/data/pokemon/base_stats/smoochum.asm +++ b/data/pokemon/base_stats/smoochum.asm @@ -3,7 +3,7 @@ db 45, 30, 15, 65, 85, 65 ; hp atk def spd sat sdf - db ICE, PSYCHIC ; type + db ICE, PSYCHIC_TYPE ; type db 45 ; catch rate db 87 ; base exp db ICE_BERRY, ICE_BERRY ; items diff --git a/data/pokemon/base_stats/starmie.asm b/data/pokemon/base_stats/starmie.asm index 262cd612..337afa76 100644 --- a/data/pokemon/base_stats/starmie.asm +++ b/data/pokemon/base_stats/starmie.asm @@ -3,7 +3,7 @@ db 60, 75, 85, 115, 100, 85 ; hp atk def spd sat sdf - db WATER, PSYCHIC ; type + db WATER, PSYCHIC_TYPE ; type db 60 ; catch rate db 207 ; base exp db STARDUST, STAR_PIECE ; items diff --git a/data/pokemon/base_stats/unown.asm b/data/pokemon/base_stats/unown.asm index bf3d0f1f..b8db2883 100644 --- a/data/pokemon/base_stats/unown.asm +++ b/data/pokemon/base_stats/unown.asm @@ -3,7 +3,7 @@ db 48, 72, 48, 48, 72, 48 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 225 ; catch rate db 61 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/wobbuffet.asm b/data/pokemon/base_stats/wobbuffet.asm index e04d443a..855a7d99 100644 --- a/data/pokemon/base_stats/wobbuffet.asm +++ b/data/pokemon/base_stats/wobbuffet.asm @@ -3,7 +3,7 @@ db 190, 33, 58, 33, 33, 58 ; hp atk def spd sat sdf - db PSYCHIC, PSYCHIC ; type + db PSYCHIC_TYPE, PSYCHIC_TYPE ; type db 45 ; catch rate db 177 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/pokemon/base_stats/xatu.asm b/data/pokemon/base_stats/xatu.asm index d0fe363f..f1fc7a55 100644 --- a/data/pokemon/base_stats/xatu.asm +++ b/data/pokemon/base_stats/xatu.asm @@ -3,7 +3,7 @@ db 65, 75, 70, 95, 95, 70 ; hp atk def spd sat sdf - db PSYCHIC, FLYING ; type + db PSYCHIC_TYPE, FLYING ; type db 75 ; catch rate db 171 ; base exp db NO_ITEM, NO_ITEM ; items diff --git a/data/types/type_boost_items.asm b/data/types/type_boost_items.asm new file mode 100644 index 00000000..85a58db1 --- /dev/null +++ b/data/types/type_boost_items.asm @@ -0,0 +1,19 @@ +TypeBoostItems: + db HELD_NORMAL_BOOST, NORMAL ; PINK_BOW/POLKADOT_BOW + db HELD_FIGHTING_BOOST, FIGHTING ; BLACKBELT_I + db HELD_FLYING_BOOST, FLYING ; SHARP_BEAK + db HELD_POISON_BOOST, POISON ; POISON BARB + db HELD_GROUND_BOOST, GROUND ; SOFT_SAND + db HELD_ROCK_BOOST, ROCK ; HARD_STONE + db HELD_BUG_BOOST, BUG ; SILVERPOWDER + db HELD_GHOST_BOOST, GHOST ; SPELL_TAG + db HELD_FIRE_BOOST, FIRE ; CHARCOAL + db HELD_WATER_BOOST, WATER ; MYSTIC WATER + db HELD_GRASS_BOOST, GRASS ; MIRACLE_SEED + db HELD_ELECTRIC_BOOST, ELECTRIC ; MAGNET + db HELD_PSYCHIC_BOOST, PSYCHIC_TYPE ; TWISTEDSPOON + db HELD_ICE_BOOST, ICE ; NEVERMELTICE + db HELD_DRAGON_BOOST, DRAGON ; DRAGON_SCALE + db HELD_DARK_BOOST, DARK ; BLACKGLASSES + db HELD_STEEL_BOOST, STEEL ; METAL_COAT + db -1 diff --git a/data/types/type_matchups.asm b/data/types/type_matchups.asm new file mode 100644 index 00000000..81906b0f --- /dev/null +++ b/data/types/type_matchups.asm @@ -0,0 +1,118 @@ +TypeMatchups: + ; attacker, defender, *= + db NORMAL, ROCK, NOT_VERY_EFFECTIVE + db NORMAL, STEEL, NOT_VERY_EFFECTIVE + db FIRE, FIRE, NOT_VERY_EFFECTIVE + db FIRE, WATER, NOT_VERY_EFFECTIVE + db FIRE, GRASS, SUPER_EFFECTIVE + db FIRE, ICE, SUPER_EFFECTIVE + db FIRE, BUG, SUPER_EFFECTIVE + db FIRE, ROCK, NOT_VERY_EFFECTIVE + db FIRE, DRAGON, NOT_VERY_EFFECTIVE + db FIRE, STEEL, SUPER_EFFECTIVE + db WATER, FIRE, SUPER_EFFECTIVE + db WATER, WATER, NOT_VERY_EFFECTIVE + db WATER, GRASS, NOT_VERY_EFFECTIVE + db WATER, GROUND, SUPER_EFFECTIVE + db WATER, ROCK, SUPER_EFFECTIVE + db WATER, DRAGON, NOT_VERY_EFFECTIVE + db ELECTRIC, WATER, SUPER_EFFECTIVE + db ELECTRIC, ELECTRIC, NOT_VERY_EFFECTIVE + db ELECTRIC, GRASS, NOT_VERY_EFFECTIVE + db ELECTRIC, GROUND, NO_EFFECT + db ELECTRIC, FLYING, SUPER_EFFECTIVE + db ELECTRIC, DRAGON, NOT_VERY_EFFECTIVE + db GRASS, FIRE, NOT_VERY_EFFECTIVE + db GRASS, WATER, SUPER_EFFECTIVE + db GRASS, GRASS, NOT_VERY_EFFECTIVE + db GRASS, POISON, NOT_VERY_EFFECTIVE + db GRASS, GROUND, SUPER_EFFECTIVE + db GRASS, FLYING, NOT_VERY_EFFECTIVE + db GRASS, BUG, NOT_VERY_EFFECTIVE + db GRASS, ROCK, SUPER_EFFECTIVE + db GRASS, DRAGON, NOT_VERY_EFFECTIVE + db GRASS, STEEL, NOT_VERY_EFFECTIVE + db ICE, WATER, NOT_VERY_EFFECTIVE + db ICE, GRASS, SUPER_EFFECTIVE + db ICE, ICE, NOT_VERY_EFFECTIVE + db ICE, GROUND, SUPER_EFFECTIVE + db ICE, FLYING, SUPER_EFFECTIVE + db ICE, DRAGON, SUPER_EFFECTIVE + db ICE, STEEL, NOT_VERY_EFFECTIVE + db ICE, FIRE, NOT_VERY_EFFECTIVE + db FIGHTING, NORMAL, SUPER_EFFECTIVE + db FIGHTING, ICE, SUPER_EFFECTIVE + db FIGHTING, POISON, NOT_VERY_EFFECTIVE + db FIGHTING, FLYING, NOT_VERY_EFFECTIVE + db FIGHTING, PSYCHIC_TYPE, NOT_VERY_EFFECTIVE + db FIGHTING, BUG, NOT_VERY_EFFECTIVE + db FIGHTING, ROCK, SUPER_EFFECTIVE + db FIGHTING, DARK, SUPER_EFFECTIVE + db FIGHTING, STEEL, SUPER_EFFECTIVE + db POISON, GRASS, SUPER_EFFECTIVE + db POISON, POISON, NOT_VERY_EFFECTIVE + db POISON, GROUND, NOT_VERY_EFFECTIVE + db POISON, ROCK, NOT_VERY_EFFECTIVE + db POISON, GHOST, NOT_VERY_EFFECTIVE + db POISON, STEEL, NO_EFFECT + db GROUND, FIRE, SUPER_EFFECTIVE + db GROUND, ELECTRIC, SUPER_EFFECTIVE + db GROUND, GRASS, NOT_VERY_EFFECTIVE + db GROUND, POISON, SUPER_EFFECTIVE + db GROUND, FLYING, NO_EFFECT + db GROUND, BUG, NOT_VERY_EFFECTIVE + db GROUND, ROCK, SUPER_EFFECTIVE + db GROUND, STEEL, SUPER_EFFECTIVE + db FLYING, ELECTRIC, NOT_VERY_EFFECTIVE + db FLYING, GRASS, SUPER_EFFECTIVE + db FLYING, FIGHTING, SUPER_EFFECTIVE + db FLYING, BUG, SUPER_EFFECTIVE + db FLYING, ROCK, NOT_VERY_EFFECTIVE + db FLYING, STEEL, NOT_VERY_EFFECTIVE + db PSYCHIC_TYPE, FIGHTING, SUPER_EFFECTIVE + db PSYCHIC_TYPE, POISON, SUPER_EFFECTIVE + db PSYCHIC_TYPE, PSYCHIC_TYPE, NOT_VERY_EFFECTIVE + db PSYCHIC_TYPE, DARK, NO_EFFECT + db PSYCHIC_TYPE, STEEL, NOT_VERY_EFFECTIVE + db BUG, FIRE, NOT_VERY_EFFECTIVE + db BUG, GRASS, SUPER_EFFECTIVE + db BUG, FIGHTING, NOT_VERY_EFFECTIVE + db BUG, POISON, NOT_VERY_EFFECTIVE + db BUG, FLYING, NOT_VERY_EFFECTIVE + db BUG, PSYCHIC_TYPE, SUPER_EFFECTIVE + db BUG, GHOST, NOT_VERY_EFFECTIVE + db BUG, DARK, SUPER_EFFECTIVE + db BUG, STEEL, NOT_VERY_EFFECTIVE + db ROCK, FIRE, SUPER_EFFECTIVE + db ROCK, ICE, SUPER_EFFECTIVE + db ROCK, FIGHTING, NOT_VERY_EFFECTIVE + db ROCK, GROUND, NOT_VERY_EFFECTIVE + db ROCK, FLYING, SUPER_EFFECTIVE + db ROCK, BUG, SUPER_EFFECTIVE + db ROCK, STEEL, NOT_VERY_EFFECTIVE + db GHOST, NORMAL, NO_EFFECT + db GHOST, PSYCHIC_TYPE, SUPER_EFFECTIVE + db GHOST, DARK, NOT_VERY_EFFECTIVE + db GHOST, STEEL, NOT_VERY_EFFECTIVE + db GHOST, GHOST, SUPER_EFFECTIVE + db DRAGON, DRAGON, SUPER_EFFECTIVE + db DRAGON, STEEL, NOT_VERY_EFFECTIVE + db DARK, FIGHTING, NOT_VERY_EFFECTIVE + db DARK, PSYCHIC_TYPE, SUPER_EFFECTIVE + db DARK, GHOST, SUPER_EFFECTIVE + db DARK, DARK, NOT_VERY_EFFECTIVE + db DARK, STEEL, NOT_VERY_EFFECTIVE + db STEEL, FIRE, NOT_VERY_EFFECTIVE + db STEEL, WATER, NOT_VERY_EFFECTIVE + db STEEL, ELECTRIC, NOT_VERY_EFFECTIVE + db STEEL, ICE, SUPER_EFFECTIVE + db STEEL, ROCK, SUPER_EFFECTIVE + db STEEL, STEEL, NOT_VERY_EFFECTIVE + + db -2 ; end (with Foresight) + +; Foresight removes Ghost's immunities. + db NORMAL, GHOST, NO_EFFECT + db FIGHTING, GHOST, NO_EFFECT + + db -1 ; end diff --git a/engine/battle/effect_commands.asm b/engine/battle/effect_commands.asm index 023730ac..7734c66f 100644 --- a/engine/battle/effect_commands.asm +++ b/engine/battle/effect_commands.asm @@ -1219,3 +1219,2355 @@ INCLUDE "data/moves/critical_hit_moves.asm" INCLUDE "data/battle/critical_hit_chances.asm" INCLUDE "engine/battle/move_effects/triple_kick.asm" + +BattleCommand_Stab: +; STAB = Same Type Attack Bonus + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + cp STRUGGLE + ret z + + ld hl, wBattleMonType1 + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wEnemyMonType1 + ld a, [hli] + ld d, a + ld e, [hl] + + ldh a, [hBattleTurn] + and a + jr z, .go ; Who Attacks and who Defends + + ld hl, wEnemyMonType1 + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wBattleMonType1 + ld a, [hli] + ld d, a + ld e, [hl] + +.go + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVarAddr + ld [wCurType], a + + push hl + push de + push bc + farcall DoWeatherModifiers + pop bc + pop de + pop hl + + push de + push bc + farcall DoBadgeTypeBoosts + pop bc + pop de + + ld a, [wCurType] + cp b + jr z, .stab + cp c + jr z, .stab + + jr .SkipStab + +.stab + ld hl, wCurDamage + 1 + ld a, [hld] + ld h, [hl] + ld l, a + + ld b, h + ld c, l + srl b + rr c + add hl, bc + + ld a, h + ld [wCurDamage], a + ld a, l + ld [wCurDamage + 1], a + + ld hl, wTypeModifier + set 7, [hl] + +.SkipStab: + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVar + ld b, a + ld hl, TypeMatchups + +.TypesLoop: + ld a, [hli] + + cp -1 + jr z, .end + + ; foresight + cp -2 + jr nz, .SkipForesightCheck + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVar + bit SUBSTATUS_IDENTIFIED, a + jr nz, .end + + jr .TypesLoop + +.SkipForesightCheck: + cp b + jr nz, .SkipType + ld a, [hl] + cp d + jr z, .GotMatchup + cp e + jr z, .GotMatchup + jr .SkipType + +.GotMatchup: + push hl + push bc + inc hl + ld a, [wTypeModifier] + and %10000000 + ld b, a +; If the target is immune to the move, treat it as a miss and calculate the damage as 0 + ld a, [hl] + and a + jr nz, .NotImmune + inc a + ld [wAttackMissed], a + xor a +.NotImmune: + ldh [hMultiplier], a + add b + ld [wTypeModifier], a + + xor a + ldh [hMultiplicand + 0], a + + ld hl, wCurDamage + ld a, [hli] + ldh [hMultiplicand + 1], a + ld a, [hld] + ldh [hMultiplicand + 2], a + + call Multiply + + ldh a, [hProduct + 1] + ld b, a + ldh a, [hProduct + 2] + or b + ld b, a + ldh a, [hProduct + 3] + or b + jr z, .ok ; This is a very convoluted way to get back that we've essentially dealt no damage. + +; Take the product and divide it by 10. + ld a, 10 + ldh [hDivisor], a + ld b, 4 + call Divide + ldh a, [hQuotient + 2] + ld b, a + ldh a, [hQuotient + 3] + or b + jr nz, .ok + + ld a, 1 + ldh [hMultiplicand + 2], a + +.ok + ldh a, [hMultiplicand + 1] + ld [hli], a + ldh a, [hMultiplicand + 2] + ld [hl], a + pop bc + pop hl + +.SkipType: + inc hl + inc hl + jr .TypesLoop + +.end + call BattleCheckTypeMatchup + ld a, [wTypeMatchup] + ld b, a + ld a, [wTypeModifier] + and %10000000 + or b + ld [wTypeModifier], a + ret + +BattleCheckTypeMatchup: + ld hl, wEnemyMonType1 + ldh a, [hBattleTurn] + and a + jr z, CheckTypeMatchup + ld hl, wBattleMonType1 +CheckTypeMatchup: +; There is an incorrect assumption about this function made in the AI related code: when +; the AI calls CheckTypeMatchup (not BattleCheckTypeMatchup), it assumes that placing the +; offensive type in a will make this function do the right thing. Since a is overwritten, +; this assumption is incorrect. A simple fix would be to load the move type for the +; current move into a in BattleCheckTypeMatchup, before falling through, which is +; consistent with how the rest of the code assumes this code works like. + push hl + push de + push bc + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVar + ld d, a + ld b, [hl] + inc hl + ld c, [hl] + ld a, 10 ; 1.0 + ld [wTypeMatchup], a + ld hl, TypeMatchups +.TypesLoop: + ld a, [hli] + cp -1 + jr z, .End + cp -2 + jr nz, .Next + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVar + bit SUBSTATUS_IDENTIFIED, a + jr nz, .End + jr .TypesLoop + +.Next: + cp d + jr nz, .Nope + ld a, [hli] + cp b + jr z, .Yup + cp c + jr z, .Yup + jr .Nope2 + +.Nope: + inc hl +.Nope2: + inc hl + jr .TypesLoop + +.Yup: + xor a + ldh [hDividend + 0], a + ldh [hMultiplicand + 0], a + ldh [hMultiplicand + 1], a + ld a, [hli] + ldh [hMultiplicand + 2], a + ld a, [wTypeMatchup] + ldh [hMultiplier], a + call Multiply + ld a, 10 + ldh [hDivisor], a + push bc + ld b, 4 + call Divide + pop bc + ldh a, [hQuotient + 3] + ld [wTypeMatchup], a + jr .TypesLoop + +.End: + pop bc + pop de + pop hl + ret + +BattleCommand_ResetTypeMatchup: +; Reset the type matchup multiplier to 1.0, if the type matchup is not 0. +; If there is immunity in play, the move automatically misses. + call BattleCheckTypeMatchup + ld a, [wTypeMatchup] + and a + ld a, 10 ; 1.0 + jr nz, .reset + call ResetDamage + xor a + ld [wTypeModifier], a + inc a + ld [wAttackMissed], a + ret + +.reset + ld [wTypeMatchup], a + ret + +INCLUDE "engine/battle/ai/switch.asm" + +INCLUDE "data/types/type_matchups.asm" + +BattleCommand_DamageVariation: +; damagevariation + +; Modify the damage spread between 85% and 100%. + +; Because of the method of division the probability distribution +; is not consistent. This makes the highest damage multipliers +; rarer than normal. + +; No point in reducing 1 or 0 damage. + ld hl, wCurDamage + ld a, [hli] + and a + jr nz, .go + ld a, [hl] + cp 2 + ret c + +.go +; Start with the maximum damage. + xor a + ldh [hMultiplicand + 0], a + dec hl + ld a, [hli] + ldh [hMultiplicand + 1], a + ld a, [hl] + ldh [hMultiplicand + 2], a + +; Multiply by 85-100%... +.loop + call BattleRandom + rrca + cp 85 percent + 1 + jr c, .loop + + ldh [hMultiplier], a + call Multiply + +; ...divide by 100%... + ld a, $ff ; 100% + ldh [hDivisor], a + ld b, $4 + call Divide + +; ...to get .85-1.00x damage. + ldh a, [hQuotient + 2] + ld hl, wCurDamage + ld [hli], a + ldh a, [hQuotient + 3] + ld [hl], a + ret + +BattleCommand_CheckHit: +; checkhit + + call .DreamEater + jp z, .Miss + + call .Protect + jp nz, .Miss + + call .DrainSub + jp z, .Miss + + call .LockOn + ret nz + + call .FlyDigMoves + jp nz, .Miss + + call .ThunderRain + ret z + + call .XAccuracy + ret nz + + ; Perfect-accuracy moves + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_ALWAYS_HIT + ret z + + call .StatModifiers + + ld a, [wPlayerMoveStruct + MOVE_ACC] + ld b, a + ldh a, [hBattleTurn] + and a + jr z, .BrightPowder + ld a, [wEnemyMoveStruct + MOVE_ACC] + ld b, a + +.BrightPowder: + push bc + call GetOpponentItem + ld a, b + cp HELD_BRIGHTPOWDER + ld a, c ; % miss + pop bc + jr nz, .skip_brightpowder + + ld c, a + ld a, b + sub c + ld b, a + jr nc, .skip_brightpowder + ld b, 0 + +.skip_brightpowder + ld a, b + cp -1 + jr z, .Hit + + call BattleRandom + cp b + jr nc, .Miss + +.Hit: + ret + +.Miss: +; Keep the damage value intact if we're using (Hi) Jump Kick. + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_JUMP_KICK + jr z, .Missed + call ResetDamage + +.Missed: + ld a, 1 + ld [wAttackMissed], a + ret + +.DreamEater: +; Return z if we're trying to eat the dream of +; a monster that isn't sleeping. + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_DREAM_EATER + ret nz + + ld a, BATTLE_VARS_STATUS_OPP + call GetBattleVar + and SLP + ret + +.Protect: +; Return nz if the opponent is protected. + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVar + bit SUBSTATUS_PROTECT, a + ret z + + ld c, 40 + call DelayFrames + +; 'protecting itself!' + ld hl, ProtectingItselfText + call StdBattleTextbox + + ld c, 40 + call DelayFrames + + ld a, 1 + and a + ret + +.LockOn: +; Return nz if we are locked-on and aren't trying to use Earthquake, +; Fissure or Magnitude on a monster that is flying. + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + bit SUBSTATUS_LOCK_ON, [hl] + res SUBSTATUS_LOCK_ON, [hl] + ret z + + ld a, BATTLE_VARS_SUBSTATUS3_OPP + call GetBattleVar + bit SUBSTATUS_FLYING, a + jr z, .LockedOn + + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + + cp EARTHQUAKE + ret z + cp FISSURE + ret z + cp MAGNITUDE + ret z + +.LockedOn: + ld a, 1 + and a + ret + +.DrainSub: +; Return z if using an HP drain move on a substitute. + call CheckSubstituteOpp + jr z, .not_draining_sub + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + + cp EFFECT_LEECH_HIT + ret z + cp EFFECT_DREAM_EATER + ret z + +.not_draining_sub + ld a, 1 + and a + ret + +.FlyDigMoves: +; Check for moves that can hit underground/flying opponents. +; Return z if the current move can hit the opponent. + + ld a, BATTLE_VARS_SUBSTATUS3_OPP + call GetBattleVar + and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND + ret z + + bit SUBSTATUS_FLYING, a + jr z, .DigMoves + + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + + cp GUST + ret z + cp WHIRLWIND + ret z + cp THUNDER + ret z + cp TWISTER + ret + +.DigMoves: + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + + cp EARTHQUAKE + ret z + cp FISSURE + ret z + cp MAGNITUDE + ret + +.ThunderRain: +; Return z if the current move always hits in rain, and it is raining. + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_THUNDER + ret nz + + ld a, [wBattleWeather] + cp WEATHER_RAIN + ret + +.XAccuracy: + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVar + bit SUBSTATUS_X_ACCURACY, a + ret + +.StatModifiers: + ldh a, [hBattleTurn] + and a + + ; load the user's accuracy into b and the opponent's evasion into c. + ld hl, wPlayerMoveStruct + MOVE_ACC + ld a, [wPlayerAccLevel] + ld b, a + ld a, [wEnemyEvaLevel] + ld c, a + + jr z, .got_acc_eva + + ld hl, wEnemyMoveStruct + MOVE_ACC + ld a, [wEnemyAccLevel] + ld b, a + ld a, [wPlayerEvaLevel] + ld c, a + +.got_acc_eva + cp b + jr c, .skip_foresight_check + + ; if the target's evasion is greater than the user's accuracy, + ; check the target's foresight status + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVar + bit SUBSTATUS_IDENTIFIED, a + ret nz + +.skip_foresight_check + ; subtract evasion from 14 + ld a, MAX_STAT_LEVEL + 1 + sub c + ld c, a + ; store the base move accuracy for math ops + xor a + ldh [hMultiplicand + 0], a + ldh [hMultiplicand + 1], a + ld a, [hl] + ldh [hMultiplicand + 2], a + push hl + ld d, 2 ; do this twice, once for the user's accuracy and once for the target's evasion + +.accuracy_loop + ; look up the multiplier from the table + push bc + ld hl, AccuracyLevelMultipliers + dec b + sla b + ld c, b + ld b, 0 + add hl, bc + pop bc + ; multiply by the first byte in that row... + ld a, [hli] + ldh [hMultiplier], a + call Multiply + ; ... and divide by the second byte + ld a, [hl] + ldh [hDivisor], a + ld b, 4 + call Divide + ; minimum accuracy is $0001 + ldh a, [hQuotient + 3] + ld b, a + ldh a, [hQuotient + 2] + or b + jr nz, .min_accuracy + ldh [hQuotient + 2], a + ld a, 1 + ldh [hQuotient + 3], a + +.min_accuracy + ; do the same thing to the target's evasion + ld b, c + dec d + jr nz, .accuracy_loop + + ; if the result is more than 2 bytes, max out at 100% + ldh a, [hQuotient + 2] + and a + ldh a, [hQuotient + 3] + jr z, .finish_accuracy + ld a, $ff + +.finish_accuracy + pop hl + ld [hl], a + ret + +INCLUDE "data/battle/accuracy_multipliers.asm" + +BattleCommand_EffectChance: +; effectchance + + xor a + ld [wEffectFailed], a + call CheckSubstituteOpp + jr nz, .failed + + push hl + ld hl, wPlayerMoveStruct + MOVE_CHANCE + ldh a, [hBattleTurn] + and a + jr z, .got_move_chance + ld hl, wEnemyMoveStruct + MOVE_CHANCE +.got_move_chance + + ; BUG: 1/256 chance to fail even for a 100% effect chance, + ; since carry is not set if BattleRandom == [hl] == 255 + call BattleRandom + cp [hl] + pop hl + ret c + +.failed + ld a, 1 + ld [wEffectFailed], a + and a + ret + +BattleCommand_LowerSub: +; lowersub + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVar + bit SUBSTATUS_SUBSTITUTE, a + ret z + + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + bit SUBSTATUS_CHARGED, a + jr nz, .already_charged + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_RAZOR_WIND + jr z, .charge_turn + cp EFFECT_SKY_ATTACK + jr z, .charge_turn + cp EFFECT_SKULL_BASH + jr z, .charge_turn + cp EFFECT_SOLARBEAM + jr z, .charge_turn + cp EFFECT_FLY + jr z, .charge_turn + +.already_charged + call .Rampage + jr z, .charge_turn + + call CheckUserIsCharging + ret nz + +.charge_turn + ; check battle scene + ld a, [wOptions] + add a + jr c, .mimic_anims + + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + inc a + ld [wKickCounter], a + ld a, SUBSTITUTE + jp LoadAnim + +.mimic_anims + call BattleCommand_LowerSubNoAnim + jp BattleCommand_MoveDelay + +.Rampage: + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_ROLLOUT + jr z, .rollout_rampage + cp EFFECT_RAMPAGE + jr z, .rollout_rampage + + ld a, 1 + and a + ret + +.rollout_rampage + ld a, [wSomeoneIsRampaging] + and a + ld a, 0 + ld [wSomeoneIsRampaging], a + ret + +BattleCommand_MoveAnim: +; moveanim + call BattleCommand_LowerSub + call BattleCommand_MoveAnimNoSub + jp BattleCommand_RaiseSub + +BattleCommand_MoveAnimNoSub: + ld a, [wAttackMissed] + and a + jp nz, BattleCommand_MoveDelay + + ldh a, [hBattleTurn] + and a + ld de, wPlayerRolloutCount + ld a, BATTLEANIM_ENEMY_DAMAGE + jr z, .got_rollout_count + ld de, wEnemyRolloutCount + ld a, BATTLEANIM_PLAYER_DAMAGE + +.got_rollout_count + ld [wNumHits], a + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_MULTI_HIT + jr z, .alternate_anim + cp EFFECT_CONVERSION + jr z, .alternate_anim + cp EFFECT_DOUBLE_HIT + jr z, .alternate_anim + cp EFFECT_POISON_MULTI_HIT + jr z, .alternate_anim + cp EFFECT_TRIPLE_KICK + jr z, .triplekick + xor a + ld [wKickCounter], a + +.triplekick + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + ld e, a + ld d, 0 + call PlayFXAnimID + + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + cp FLY + jr z, .clear_sprite + cp DIG + ret nz +.clear_sprite + jp AppearUserLowerSub + +.alternate_anim + ld a, [wKickCounter] + and 1 + xor 1 + ld [wKickCounter], a + ld a, [de] + cp 1 + push af + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + ld e, a + ld d, 0 + pop af + jp z, PlayFXAnimID + xor a + ld [wNumHits], a + jp PlayFXAnimID + +BattleCommand_StatUpAnim: + ld a, [wAttackMissed] + and a + jp nz, BattleCommand_MoveDelay + + xor a + jr BattleCommand_StatUpDownAnim + +BattleCommand_StatDownAnim: + ld a, [wAttackMissed] + and a + jp nz, BattleCommand_MoveDelay + + ldh a, [hBattleTurn] + and a + ld a, BATTLEANIM_ENEMY_STAT_DOWN + jr z, BattleCommand_StatUpDownAnim + ld a, BATTLEANIM_WOBBLE + + ; fallthrough + +BattleCommand_StatUpDownAnim: + ld [wNumHits], a + xor a + ld [wKickCounter], a + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + ld e, a + ld d, 0 + jp PlayFXAnimID + +BattleCommand_SwitchTurn: +; switchturn + + ldh a, [hBattleTurn] + xor 1 + ldh [hBattleTurn], a + ret + +BattleCommand_RaiseSub: +; raisesub + + ld a, BATTLE_VARS_SUBSTATUS4 + call GetBattleVar + bit SUBSTATUS_SUBSTITUTE, a + ret z + + ; check battle scene + ld a, [wOptions] + add a + jp c, BattleCommand_RaiseSubNoAnim + + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + ld a, $2 + ld [wKickCounter], a + ld a, SUBSTITUTE + jp LoadAnim + +BattleCommand_FailureText: +; failuretext +; If the move missed or failed, load the appropriate +; text, and end the effects of multi-turn or multi- +; hit moves. + ld a, [wAttackMissed] + and a + ret z + + call GetFailureResultText + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVarAddr + + cp FLY + jr z, .fly_dig + cp DIG + jr z, .fly_dig + +; Move effect: + inc hl + ld a, [hl] + + cp EFFECT_MULTI_HIT + jr z, .multihit + cp EFFECT_DOUBLE_HIT + jr z, .multihit + cp EFFECT_POISON_MULTI_HIT + jr z, .multihit + jp EndMoveEffect + +.multihit + call BattleCommand_RaiseSub + jp EndMoveEffect + +.fly_dig + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVarAddr + res SUBSTATUS_UNDERGROUND, [hl] + res SUBSTATUS_FLYING, [hl] + call AppearUserRaiseSub + jp EndMoveEffect + +BattleCommand_ApplyDamage: +; applydamage + + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVar + bit SUBSTATUS_ENDURE, a + jr z, .focus_band + + call BattleCommand_FalseSwipe + ld b, 0 + jr nc, .damage + ld b, 1 + jr .damage + +.focus_band + call GetOpponentItem + ld a, b + cp HELD_FOCUS_BAND + ld b, 0 + jr nz, .damage + + call BattleRandom + cp c + jr nc, .damage + call BattleCommand_FalseSwipe + ld b, 0 + jr nc, .damage + ld b, 2 + +.damage + push bc + call .update_damage_taken + ld c, FALSE + ldh a, [hBattleTurn] + and a + jr nz, .damage_player + call DoEnemyDamage + jr .done_damage + +.damage_player + call DoPlayerDamage + +.done_damage + pop bc + ld a, b + and a + ret z + + dec a + jr nz, .focus_band_text + ld hl, EnduredText + jp StdBattleTextbox + +.focus_band_text + call GetOpponentItem + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetItemName + ld hl, HungOnText + jp StdBattleTextbox + +.update_damage_taken + ld a, BATTLE_VARS_SUBSTATUS4_OPP + call GetBattleVar + bit SUBSTATUS_SUBSTITUTE, a + ret nz + + ld de, wPlayerDamageTaken + 1 + ldh a, [hBattleTurn] + and a + jr nz, .got_damage_taken + ld de, wEnemyDamageTaken + 1 + +.got_damage_taken + ld a, [wCurDamage + 1] + ld b, a + ld a, [de] + add b + ld [de], a + dec de + ld a, [wCurDamage] + ld b, a + ld a, [de] + adc b + ld [de], a + ret nc + ld a, $ff + ld [de], a + inc de + ld [de], a + ret + +GetFailureResultText: + ld hl, DoesntAffectText + ld de, DoesntAffectText + ld a, [wTypeModifier] + and $7f + jr z, .got_text + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_FUTURE_SIGHT + ld hl, ButItFailedText + ld de, ItFailedText + jr z, .got_text + ld hl, AttackMissedText + ld de, AttackMissed2Text + ld a, [wCriticalHit] + cp -1 + jr nz, .got_text + ld hl, UnaffectedText +.got_text + call FailText_CheckOpponentProtect + xor a + ld [wCriticalHit], a + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_JUMP_KICK + ret nz + + ld a, [wTypeModifier] + and $7f + ret z + + ld hl, wCurDamage + ld a, [hli] + ld b, [hl] +rept 3 + srl a + rr b +endr + ld [hl], b + dec hl + ld [hli], a + or b + jr nz, .do_at_least_1_damage + inc a + ld [hl], a +.do_at_least_1_damage + ld hl, CrashedText + call StdBattleTextbox + ld a, $1 + ld [wKickCounter], a + call LoadMoveAnim + ld c, TRUE + ldh a, [hBattleTurn] + and a + jp nz, DoEnemyDamage + jp DoPlayerDamage + +FailText_CheckOpponentProtect: + ld a, BATTLE_VARS_SUBSTATUS1_OPP + call GetBattleVar + bit SUBSTATUS_PROTECT, a + jr z, .not_protected + ld h, d + ld l, e +.not_protected + jp StdBattleTextbox + +BattleCommand_BideFailText: + ld a, [wAttackMissed] + and a + ret z + + ld a, [wTypeModifier] + and $7f + jp z, PrintDoesntAffect + jp PrintButItFailed + +BattleCommand_CriticalText: +; criticaltext +; Prints the message for critical hits or one-hit KOs. + +; If there is no message to be printed, wait 20 frames. + ld a, [wCriticalHit] + and a + jr z, .wait + + dec a + add a + ld hl, .texts + ld b, 0 + ld c, a + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call StdBattleTextbox + + xor a + ld [wCriticalHit], a + +.wait + ld c, 20 + jp DelayFrames + +.texts + dw CriticalHitText + dw OneHitKOText + +BattleCommand_StartLoop: +; startloop + + ld hl, wPlayerRolloutCount + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wEnemyRolloutCount +.ok + xor a + ld [hl], a + ret + +BattleCommand_SuperEffectiveLoopText: +; supereffectivelooptext + + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVarAddr + bit SUBSTATUS_IN_LOOP, a + ret nz + + ; fallthrough + +BattleCommand_SuperEffectiveText: +; supereffectivetext + + ld a, [wTypeModifier] + and $7f + cp 10 ; 1.0 + ret z + ld hl, SuperEffectiveText + jr nc, .print + ld hl, NotVeryEffectiveText +.print + jp StdBattleTextbox + +BattleCommand_CheckFaint: +; checkfaint + +; Faint the opponent if its HP reached zero +; and faint the user along with it if it used Destiny Bond. +; Ends the move effect if the opponent faints. + + ld hl, wEnemyMonHP + ldh a, [hBattleTurn] + and a + jr z, .got_hp + ld hl, wBattleMonHP + +.got_hp + ld a, [hli] + or [hl] + ret nz + + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVar + bit SUBSTATUS_DESTINY_BOND, a + jr z, .no_dbond + + ld hl, TookDownWithItText + call StdBattleTextbox + + ldh a, [hBattleTurn] + and a + ld hl, wEnemyMonMaxHP + 1 + bccoord 2, 2 ; hp bar + ld a, 0 + jr nz, .got_max_hp + ld hl, wBattleMonMaxHP + 1 + bccoord 10, 9 ; hp bar + ld a, 1 + +.got_max_hp + ld [wWhichHPBar], a + ld a, [hld] + ld [wBuffer1], a + ld a, [hld] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer3], a + xor a + ld [hld], a + ld a, [hl] + ld [wBuffer4], a + xor a + ld [hl], a + ld [wBuffer5], a + ld [wBuffer6], a + ld h, b + ld l, c + predef AnimateHPBar + call RefreshBattleHuds + + call BattleCommand_SwitchTurn + xor a + ld [wNumHits], a + ld [wFXAnimID + 1], a + inc a + ld [wKickCounter], a + ld a, DESTINY_BOND + call LoadAnim + call BattleCommand_SwitchTurn + + jr .finish + +.no_dbond + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_MULTI_HIT + jr z, .multiple_hit_raise_sub + cp EFFECT_DOUBLE_HIT + jr z, .multiple_hit_raise_sub + cp EFFECT_POISON_MULTI_HIT + jr z, .multiple_hit_raise_sub + cp EFFECT_TRIPLE_KICK + jr z, .multiple_hit_raise_sub + cp EFFECT_BEAT_UP + jr nz, .finish + +.multiple_hit_raise_sub + call BattleCommand_RaiseSub + +.finish + jp EndMoveEffect + +BattleCommand_BuildOpponentRage: +; buildopponentrage + + jp .start + +.start + ld a, [wAttackMissed] + and a + ret nz + + ld a, BATTLE_VARS_SUBSTATUS4_OPP + call GetBattleVar + bit SUBSTATUS_RAGE, a + ret z + + ld de, wEnemyRageCounter + ldh a, [hBattleTurn] + and a + jr z, .player + ld de, wPlayerRageCounter +.player + ld a, [de] + inc a + ret z + ld [de], a + + call BattleCommand_SwitchTurn + ld hl, RageBuildingText + call StdBattleTextbox + jp BattleCommand_SwitchTurn + +BattleCommand_RageDamage: +; ragedamage + + ld a, [wCurDamage] + ld h, a + ld b, a + ld a, [wCurDamage + 1] + ld l, a + ld c, a + ldh a, [hBattleTurn] + and a + ld a, [wPlayerRageCounter] + jr z, .rage_loop + ld a, [wEnemyRageCounter] +.rage_loop + and a + jr z, .done + dec a + add hl, bc + jr nc, .rage_loop + ld hl, $ffff +.done + ld a, h + ld [wCurDamage], a + ld a, l + ld [wCurDamage + 1], a + ret + +EndMoveEffect: + ld a, [wBattleScriptBufferAddress] + ld l, a + ld a, [wBattleScriptBufferAddress + 1] + ld h, a + ld a, $ff + ld [hli], a + ld [hli], a + ld [hl], a + ret + +DittoMetalPowder: + ld a, MON_SPECIES + call BattlePartyAttr + ldh a, [hBattleTurn] + and a + ld a, [hl] + jr nz, .Ditto + ld a, [wTempEnemyMonSpecies] + +.Ditto: + cp DITTO + ret nz + + push bc + call GetOpponentItem + ld a, [hl] + cp METAL_POWDER + pop bc + ret nz + + ld a, c + srl a + add c + ld c, a + ret nc + + srl b + ld a, b + and a + jr nz, .done + inc b +.done + scf + rr c + ret + +BattleCommand_DamageStats: +; damagestats + + ldh a, [hBattleTurn] + and a + jp nz, EnemyAttackDamage + + ; fallthrough + +PlayerAttackDamage: +; Return move power d, player level e, enemy defense c and player attack b. + + call ResetDamage + + ld hl, wPlayerMoveStructPower + ld a, [hli] + and a + ld d, a + ret z + + ld a, [hl] + cp SPECIAL + jr nc, .special + +.physical + ld hl, wEnemyMonDefense + ld a, [hli] + ld b, a + ld c, [hl] + + ld a, [wEnemyScreens] + bit SCREENS_REFLECT, a + jr z, .physicalcrit + sla c + rl b + +.physicalcrit + ld hl, wBattleMonAttack + call CheckDamageStatsCritical + jr c, .thickclub + + ld hl, wEnemyDefense + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wPlayerAttack + jr .thickclub + +.special + ld hl, wEnemyMonSpclDef + ld a, [hli] + ld b, a + ld c, [hl] + + ld a, [wEnemyScreens] + bit SCREENS_LIGHT_SCREEN, a + jr z, .specialcrit + sla c + rl b + +.specialcrit + ld hl, wBattleMonSpclAtk + call CheckDamageStatsCritical + jr c, .lightball + + ld hl, wEnemySpDef + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wPlayerSpAtk + +.lightball +; Note: Returns player special attack at hl in hl. + call LightBallBoost + jr .done + +.thickclub +; Note: Returns player attack at hl in hl. + call ThickClubBoost + +.done + call TruncateHL_BC + + ld a, [wBattleMonLevel] + ld e, a + call DittoMetalPowder + + ld a, 1 + and a + ret + +TruncateHL_BC: +.loop +; Truncate 16-bit values hl and bc to 8-bit values b and c respectively. +; b = hl, c = bc + + ld a, h + or b + jr z, .done + + srl b + rr c + srl b + rr c + + ld a, c + or b + jr nz, .done_bc + inc c + +.done_bc + srl h + rr l + srl h + rr l + + ld a, l + or h + jr nz, .done + inc l + +.done + ld b, l + ret + +CheckDamageStatsCritical: +; Return carry if boosted stats should be used in damage calculations. +; Unboosted stats should be used if the attack is a critical hit, +; and the stage of the opponent's defense is higher than the user's attack. + + ld a, [wCriticalHit] + and a + scf + ret z + + push hl + push bc + ldh a, [hBattleTurn] + and a + jr nz, .enemy + ld a, [wPlayerMoveStructType] + cp SPECIAL +; special + ld a, [wPlayerSAtkLevel] + ld b, a + ld a, [wEnemySDefLevel] + jr nc, .end +; physical + ld a, [wPlayerAtkLevel] + ld b, a + ld a, [wEnemyDefLevel] + jr .end + +.enemy + ld a, [wEnemyMoveStructType] + cp SPECIAL +; special + ld a, [wEnemySAtkLevel] + ld b, a + ld a, [wPlayerSDefLevel] + jr nc, .end +; physical + ld a, [wEnemyAtkLevel] + ld b, a + ld a, [wPlayerDefLevel] +.end + cp b + pop bc + pop hl + ret + +ThickClubBoost: +; Return in hl the stat value at hl. + +; If the attacking monster is Cubone or Marowak and +; it's holding a Thick Club, double it. + push bc + push de + ld b, CUBONE + ld c, MAROWAK + ld d, THICK_CLUB + call SpeciesItemBoost + pop de + pop bc + ret + +LightBallBoost: +; Return in hl the stat value at hl. + +; If the attacking monster is Pikachu and it's +; holding a Light Ball, double it. + push bc + push de + ld b, PIKACHU + ld c, PIKACHU + ld d, LIGHT_BALL + call SpeciesItemBoost + pop de + pop bc + ret + +SpeciesItemBoost: +; Return in hl the stat value at hl. + +; If the attacking monster is species b or c and +; it's holding item d, double it. + + ld a, [hli] + ld l, [hl] + ld h, a + + push hl + ld a, MON_SPECIES + call BattlePartyAttr + + ldh a, [hBattleTurn] + and a + ld a, [hl] + jr z, .CompareSpecies + ld a, [wTempEnemyMonSpecies] +.CompareSpecies: + pop hl + + cp b + jr z, .GetItemHeldEffect + cp c + ret nz + +.GetItemHeldEffect: + push hl + call GetUserItem + ld a, [hl] + pop hl + cp d + ret nz + +; Double the stat + sla l + rl h + ret + +EnemyAttackDamage: + call ResetDamage + +; No damage dealt with 0 power. + ld hl, wEnemyMoveStructPower + ld a, [hli] ; hl = wEnemyMoveStructType + ld d, a + and a + ret z + + ld a, [hl] + cp SPECIAL + jr nc, .Special + +.physical + ld hl, wBattleMonDefense + ld a, [hli] + ld b, a + ld c, [hl] + + ld a, [wPlayerScreens] + bit SCREENS_REFLECT, a + jr z, .physicalcrit + sla c + rl b + +.physicalcrit + ld hl, wEnemyMonAttack + call CheckDamageStatsCritical + jr c, .thickclub + + ld hl, wPlayerDefense + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wEnemyAttack + jr .thickclub + +.Special: + ld hl, wBattleMonSpclDef + ld a, [hli] + ld b, a + ld c, [hl] + + ld a, [wPlayerScreens] + bit SCREENS_LIGHT_SCREEN, a + jr z, .specialcrit + sla c + rl b + +.specialcrit + ld hl, wEnemyMonSpclAtk + call CheckDamageStatsCritical + jr c, .lightball + ld hl, wPlayerSpDef + ld a, [hli] + ld b, a + ld c, [hl] + ld hl, wEnemySpAtk + +.lightball + call LightBallBoost + jr .done + +.thickclub + call ThickClubBoost + +.done + call TruncateHL_BC + + ld a, [wEnemyMonLevel] + ld e, a + call DittoMetalPowder + + ld a, 1 + and a + ret + +INCLUDE "engine/battle/move_effects/beat_up.asm" + +BattleCommand_ClearMissDamage: +; clearmissdamage + ld a, [wAttackMissed] + and a + ret z + + jp ResetDamage + +HitSelfInConfusion: + call ResetDamage + ldh a, [hBattleTurn] + and a + ld hl, wBattleMonDefense + ld de, wPlayerScreens + ld a, [wBattleMonLevel] + jr z, .got_it + + ld hl, wEnemyMonDefense + ld de, wEnemyScreens + ld a, [wEnemyMonLevel] +.got_it + push af + ld a, [hli] + ld b, a + ld c, [hl] + ld a, [de] + bit SCREENS_REFLECT, a + jr z, .mimic_screen + + sla c + rl b +.mimic_screen + dec hl + dec hl + dec hl + ld a, [hli] + ld l, [hl] + ld h, a + call TruncateHL_BC + ld d, 40 + pop af + ld e, a + ret + +BattleCommand_DamageCalc: +; damagecalc + +; Return a damage value for move power d, player level e, enemy defense c and player attack b. + +; Return 1 if successful, else 0. + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + +; Selfdestruct and Explosion halve defense. + cp EFFECT_SELFDESTRUCT + jr nz, .dont_selfdestruct + + srl c + jr nz, .dont_selfdestruct + inc c + +.dont_selfdestruct + +; Variable-hit moves and Conversion can have a power of 0. + cp EFFECT_MULTI_HIT + jr z, .skip_zero_damage_check + + cp EFFECT_CONVERSION + jr z, .skip_zero_damage_check + +; No damage if move power is 0. + ld a, d + and a + ret z + +.skip_zero_damage_check +; Minimum defense value is 1. + ld a, c + and a + jr nz, .not_dividing_by_zero + ld c, 1 +.not_dividing_by_zero + + xor a + ld hl, hDividend + ld [hli], a + ld [hli], a + ld [hl], a + +; Level * 2 + ld a, e + add a + jr nc, .level_not_overflowing + ld [hl], 1 +.level_not_overflowing + inc hl + ld [hli], a + +; / 5 + ld a, 5 + ld [hld], a + push bc + ld b, 4 + call Divide + pop bc + +; + 2 + inc [hl] + inc [hl] + +; * bp + inc hl + ld [hl], d + call Multiply + +; * Attack + ld [hl], b + call Multiply + +; / Defense + ld [hl], c + ld b, 4 + call Divide + +; / 50 + ld [hl], 50 + ld b, $4 + call Divide + +; Item boosts + call GetUserItem + + ld a, b + and a + jr z, .DoneItem + + ld hl, TypeBoostItems + +.NextItem: + ld a, [hli] + cp -1 + jr z, .DoneItem + +; Item effect + cp b + ld a, [hli] + jr nz, .NextItem + +; Type + ld b, a + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVar + cp b + jr nz, .DoneItem + +; * 100 + item effect amount + ld a, c + add 100 + ldh [hMultiplier], a + call Multiply + +; / 100 + ld a, 100 + ldh [hDivisor], a + ld b, 4 + call Divide + +.DoneItem: +; Critical hits + call .CriticalMultiplier + +; Update wCurDamage (capped at 997). + ld hl, wCurDamage + ld b, [hl] + ldh a, [hProduct + 3] + add b + ldh [hProduct + 3], a + jr nc, .dont_cap_1 + + ldh a, [hProduct + 2] + inc a + ldh [hProduct + 2], a + and a + jr z, .Cap + +.dont_cap_1 + ldh a, [hProduct] + ld b, a + ldh a, [hProduct + 1] + or a + jr nz, .Cap + + ldh a, [hProduct + 2] + cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + jr c, .dont_cap_2 + + cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + 1 + jr nc, .Cap + + ldh a, [hProduct + 3] + cp LOW(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + jr nc, .Cap + +.dont_cap_2 + inc hl + + ldh a, [hProduct + 3] + ld b, [hl] + add b + ld [hld], a + + ldh a, [hProduct + 2] + ld b, [hl] + adc b + ld [hl], a + jr c, .Cap + + ld a, [hl] + cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + jr c, .dont_cap_3 + + cp HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + 1 + jr nc, .Cap + + inc hl + ld a, [hld] + cp LOW(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE + 1) + jr c, .dont_cap_3 + +.Cap: + ld a, HIGH(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE) + ld [hli], a + ld a, LOW(MAX_STAT_VALUE - MIN_NEUTRAL_DAMAGE) + ld [hld], a + +.dont_cap_3 +; Minimum neutral damage is 2 (bringing the cap to 999). + inc hl + ld a, [hl] + add MIN_NEUTRAL_DAMAGE + ld [hld], a + jr nc, .dont_floor + inc [hl] +.dont_floor + + ld a, 1 + and a + ret + +.CriticalMultiplier: + ld a, [wCriticalHit] + and a + ret z + +; x2 + ldh a, [hQuotient + 3] + sla a + ldh [hProduct + 3], a + + ldh a, [hQuotient + 2] + rl a + ldh [hProduct + 2], a + +; Cap at $ffff. + ret nc + + ld a, $ff + ldh [hProduct + 2], a + ldh [hProduct + 3], a + + ret + +INCLUDE "data/types/type_boost_items.asm" + +BattleCommand_ConstantDamage: +; constantdamage + + ld hl, wBattleMonLevel + ldh a, [hBattleTurn] + and a + jr z, .got_turn + ld hl, wEnemyMonLevel + +.got_turn + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_LEVEL_DAMAGE + ld b, [hl] + ld a, 0 + jr z, .got_power + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVar + cp EFFECT_PSYWAVE + jr z, .psywave + + cp EFFECT_SUPER_FANG + jr z, .super_fang + + cp EFFECT_REVERSAL + jr z, .reversal + + ld a, BATTLE_VARS_MOVE_POWER + call GetBattleVar + ld b, a + ld a, $0 + jr .got_power + +.psywave + ld a, b + srl a + add b + ld b, a +.psywave_loop + call BattleRandom + and a + jr z, .psywave_loop + cp b + jr nc, .psywave_loop + ld b, a + ld a, 0 + jr .got_power + +.super_fang + ld hl, wEnemyMonHP + ldh a, [hBattleTurn] + and a + jr z, .got_hp + ld hl, wBattleMonHP +.got_hp + ld a, [hli] + srl a + ld b, a + ld a, [hl] + rr a + push af + ld a, b + pop bc + and a + jr nz, .got_power + or b + ld a, 0 + jr nz, .got_power + ld b, 1 + jr .got_power + +.got_power + ld hl, wCurDamage + ld [hli], a + ld [hl], b + ret + +.reversal + ld hl, wBattleMonHP + ldh a, [hBattleTurn] + and a + jr z, .reversal_got_hp + ld hl, wEnemyMonHP +.reversal_got_hp + xor a + ldh [hDividend], a + ldh [hMultiplicand + 0], a + ld a, [hli] + ldh [hMultiplicand + 1], a + ld a, [hli] + ldh [hMultiplicand + 2], a + ld a, 48 + ldh [hMultiplier], a + call Multiply + ld a, [hli] + ld b, a + ld a, [hl] + ldh [hDivisor], a + ld a, b + and a + jr z, .skip_to_divide + + ldh a, [hProduct + 4] + srl b + rr a + srl b + rr a + ldh [hDivisor], a + ldh a, [hProduct + 2] + ld b, a + srl b + ldh a, [hProduct + 3] + rr a + srl b + rr a + ldh [hDividend + 3], a + ld a, b + ldh [hDividend + 2], a + +.skip_to_divide + ld b, 4 + call Divide + ldh a, [hQuotient + 3] + ld b, a + ld hl, FlailReversalPower + +.reversal_loop + ld a, [hli] + cp b + jr nc, .break_loop + inc hl + jr .reversal_loop + +.break_loop + ldh a, [hBattleTurn] + and a + ld a, [hl] + jr nz, .notPlayersTurn + + ld hl, wPlayerMoveStructPower + ld [hl], a + push hl + call PlayerAttackDamage + jr .notEnemysTurn + +.notPlayersTurn + ld hl, wEnemyMoveStructPower + ld [hl], a + push hl + call EnemyAttackDamage + +.notEnemysTurn + call BattleCommand_DamageCalc + pop hl + ld [hl], 1 + ret + +INCLUDE "data/moves/flail_reversal_power.asm" + +INCLUDE "engine/battle/move_effects/counter.asm" + +INCLUDE "engine/battle/move_effects/encore.asm" + +INCLUDE "engine/battle/move_effects/pain_split.asm" + +INCLUDE "engine/battle/move_effects/snore.asm" + +INCLUDE "engine/battle/move_effects/conversion2.asm" + +INCLUDE "engine/battle/move_effects/lock_on.asm" + +INCLUDE "engine/battle/move_effects/sketch.asm" + +BattleCommand_DefrostOpponent: +; defrostopponent +; Thaw the opponent if frozen, and +; raise the user's Attack one stage. + + call AnimateCurrentMove + + ld a, BATTLE_VARS_STATUS_OPP + call GetBattleVarAddr + call Defrost + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVarAddr + ld a, [hl] + push hl + push af + + ld a, EFFECT_ATTACK_UP + ld [hl], a + call BattleCommand_StatUp + + pop af + pop hl + ld [hl], a + ret + +INCLUDE "engine/battle/move_effects/sleep_talk.asm" + +INCLUDE "engine/battle/move_effects/destiny_bond.asm" + +INCLUDE "engine/battle/move_effects/spite.asm" + +INCLUDE "engine/battle/move_effects/false_swipe.asm" + +INCLUDE "engine/battle/move_effects/heal_bell.asm" + +FarPlayBattleAnimation: +; play animation de + + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND + ret nz + + ; fallthrough + +PlayFXAnimID: + ld a, e + ld [wFXAnimID], a + ld a, d + ld [wFXAnimID + 1], a + + ld c, 3 + call DelayFrames + callfar PlayBattleAnim + ret + +DoEnemyDamage: + ld hl, wCurDamage + ld a, [hli] + ld b, a + ld a, [hl] + or b + jr z, .did_no_damage + + ld a, c + and a + jr nz, .ignore_substitute + ld a, [wEnemySubStatus4] + bit SUBSTATUS_SUBSTITUTE, a + jp nz, DoSubstituteDamage + +.ignore_substitute + ; Substract wCurDamage from wEnemyMonHP. + ; store original HP in little endian wBuffer3/4 + ld a, [hld] + ld b, a + ld a, [wEnemyMonHP + 1] + ld [wBuffer3], a + sub b + ld [wEnemyMonHP + 1], a + ld a, [hl] + ld b, a + ld a, [wEnemyMonHP] + ld [wBuffer4], a + sbc b + ld [wEnemyMonHP], a + jr nc, .no_underflow + + ld a, [wBuffer4] + ld [hli], a + ld a, [wBuffer3] + ld [hl], a + xor a + ld hl, wEnemyMonHP + ld [hli], a + ld [hl], a + +.no_underflow + ld hl, wEnemyMonMaxHP + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + ld hl, wEnemyMonHP + ld a, [hli] + ld [wBuffer6], a + ld a, [hl] + ld [wBuffer5], a + + hlcoord 2, 2 + xor a + ld [wWhichHPBar], a + predef AnimateHPBar +.did_no_damage + jp RefreshBattleHuds + +DoPlayerDamage: + ld hl, wCurDamage + ld a, [hli] + ld b, a + ld a, [hl] + or b + jr z, .did_no_damage + + ld a, c + and a + jr nz, .ignore_substitute + ld a, [wPlayerSubStatus4] + bit SUBSTATUS_SUBSTITUTE, a + jp nz, DoSubstituteDamage + +.ignore_substitute + ; Substract wCurDamage from wBattleMonHP. + ; store original HP in little endian wBuffer3/4 + ; store new HP in little endian wBuffer5/6 + ld a, [hld] + ld b, a + ld a, [wBattleMonHP + 1] + ld [wBuffer3], a + sub b + ld [wBattleMonHP + 1], a + ld [wBuffer5], a + ld b, [hl] + ld a, [wBattleMonHP] + ld [wBuffer4], a + sbc b + ld [wBattleMonHP], a + ld [wBuffer6], a + jr nc, .no_underflow + + ld a, [wBuffer4] + ld [hli], a + ld a, [wBuffer3] + ld [hl], a + xor a + ld hl, wBattleMonHP + ld [hli], a + ld [hl], a + ld hl, wBuffer5 + ld [hli], a + ld [hl], a + +.no_underflow + ld hl, wBattleMonMaxHP + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + + hlcoord 10, 9 + ld a, 1 + ld [wWhichHPBar], a + predef AnimateHPBar +.did_no_damage + jp RefreshBattleHuds + +DoSubstituteDamage: + ld hl, SubTookDamageText + call StdBattleTextbox + + ld de, wEnemySubstituteHP + ldh a, [hBattleTurn] + and a + jr z, .got_hp + ld de, wPlayerSubstituteHP +.got_hp + + ld hl, wCurDamage + ld a, [hli] + and a + jr nz, .broke + + ld a, [de] + sub [hl] + ld [de], a + jr z, .broke + jr nc, .done + +.broke + ld a, BATTLE_VARS_SUBSTATUS4_OPP + call GetBattleVarAddr + res SUBSTATUS_SUBSTITUTE, [hl] + + ld hl, SubFadedText + call StdBattleTextbox + + call BattleCommand_SwitchTurn + call BattleCommand_LowerSubNoAnim + ld a, BATTLE_VARS_SUBSTATUS3 + call GetBattleVar + and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND + call z, AppearUserLowerSub + call BattleCommand_SwitchTurn + + ld a, BATTLE_VARS_MOVE_EFFECT + call GetBattleVarAddr + cp EFFECT_MULTI_HIT + jr z, .ok + cp EFFECT_DOUBLE_HIT + jr z, .ok + cp EFFECT_POISON_MULTI_HIT + jr z, .ok + cp EFFECT_TRIPLE_KICK + jr z, .ok + cp EFFECT_BEAT_UP + jr z, .ok + xor a + ld [hl], a +.ok + call RefreshBattleHuds +.done + jp ResetDamage diff --git a/engine/battle/move_effects/beat_up.asm b/engine/battle/move_effects/beat_up.asm new file mode 100644 index 00000000..8546c37d --- /dev/null +++ b/engine/battle/move_effects/beat_up.asm @@ -0,0 +1,220 @@ +BattleCommand_BeatUp: +; beatup + + call ResetDamage + ldh a, [hBattleTurn] + and a + jp nz, .enemy_beats_up + + ld a, [wPlayerSubStatus3] + bit SUBSTATUS_IN_LOOP, a + jr nz, .next_mon + + ld c, 20 + call DelayFrames + xor a + ld [wPlayerRolloutCount], a + ld [wceed], a + ld [wBeatUpHitAtLeastOnce], a + jr .got_mon + +.next_mon + ld a, [wPlayerRolloutCount] + ld b, a + ld a, [wPartyCount] + sub b + ld [wceed], a + +.got_mon + ld a, [wceed] + ld hl, wPartyMonNicknames + call GetNick + ld a, MON_HP + call GetBeatupMonLocation + ld a, [hli] + or [hl] + jp z, .beatup_fail ; fainted + ld a, [wceed] + ld c, a + ld a, [wCurBattleMon] + ; BUG: this can desynchronize link battles + ; Change "cp [hl]" to "cp c" to fix + cp [hl] + ld hl, wBattleMonStatus + jr z, .active_mon + ld a, MON_STATUS + call GetBeatupMonLocation +.active_mon + ld a, [hl] + and a + jp nz, .beatup_fail + + ld a, $1 + ld [wBeatUpHitAtLeastOnce], a + ld hl, BeatUpAttackText + call StdBattleTextbox + + ld a, [wEnemyMonSpecies] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseDefense] + ld c, a + + push bc + ld a, MON_SPECIES + call GetBeatupMonLocation + ld a, [hl] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseAttack] + pop bc + ld b, a + + push bc + ld a, MON_LEVEL + call GetBeatupMonLocation + ld a, [hl] + ld e, a + pop bc + + ld a, [wPlayerMoveStructPower] + ld d, a + ret + +.enemy_beats_up + ld a, [wEnemySubStatus3] + bit SUBSTATUS_IN_LOOP, a + jr nz, .enemy_next_mon + + xor a + ld [wEnemyRolloutCount], a + ld [wceed], a + ld [wBeatUpHitAtLeastOnce], a + jr .enemy_got_mon + +.enemy_next_mon + ld a, [wEnemyRolloutCount] + ld b, a + ld a, [wOTPartyCount] + sub b + ld [wceed], a + +.enemy_got_mon + ld a, [wBattleMode] + dec a + jr z, .wild + + ld a, [wLinkMode] + and a + jr nz, .linked + + ld a, [wceed] + ld c, a + ld b, 0 + ld hl, wOTPartySpecies + add hl, bc + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + jr .got_enemy_nick + +.linked + ld a, [wceed] + ld hl, wOTPartyMonNicknames + ld bc, NAME_LENGTH + call AddNTimes + ld de, wStringBuffer1 + call CopyBytes + +.got_enemy_nick + ld a, MON_HP + call GetBeatupMonLocation + ld a, [hli] + or [hl] + jp z, .beatup_fail + + ld a, [wceed] + ld b, a + ld a, [wCurOTMon] + cp b + ld hl, wEnemyMonStatus + jr z, .active_enemy + ld a, MON_STATUS + call GetBeatupMonLocation +.active_enemy + ld a, [hl] + and a + jr nz, .beatup_fail + + ld a, $1 + ld [wBeatUpHitAtLeastOnce], a + jr .finish_beatup + +.wild + ld a, [wEnemyMonSpecies] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, BeatUpAttackText + call StdBattleTextbox + jp EnemyAttackDamage + +.finish_beatup + ld hl, BeatUpAttackText + call StdBattleTextbox + + ld a, [wBattleMonSpecies] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseDefense] + ld c, a + + push bc + ld a, MON_SPECIES + call GetBeatupMonLocation + ld a, [hl] + ld [wCurSpecies], a + call GetBaseData + ld a, [wBaseAttack] + pop bc + ld b, a + + push bc + ld a, MON_LEVEL + call GetBeatupMonLocation + ld a, [hl] + ld e, a + pop bc + + ld a, [wEnemyMoveStructPower] + ld d, a + ret + +.beatup_fail + ld b, buildopponentrage_command + jp SkipToBattleCommand + +BattleCommand_BeatUpFailText: +; beatupfailtext + + ld a, [wBeatUpHitAtLeastOnce] + and a + ret nz + + jp PrintButItFailed + +GetBeatupMonLocation: + push bc + ld c, a + ld b, 0 + ldh a, [hBattleTurn] + and a + ld hl, wPartyMon1Species + jr z, .got_species + ld hl, wOTPartyMon1Species + +.got_species + ld a, [wceed] + add hl, bc + call GetPartyLocation + pop bc + ret diff --git a/engine/battle/move_effects/conversion2.asm b/engine/battle/move_effects/conversion2.asm new file mode 100644 index 00000000..bc866727 --- /dev/null +++ b/engine/battle/move_effects/conversion2.asm @@ -0,0 +1,64 @@ +BattleCommand_Conversion2: +; conversion2 + + ld a, [wAttackMissed] + and a + jr nz, .failed + ld hl, wBattleMonType1 + ldh a, [hBattleTurn] + and a + jr z, .got_type + ld hl, wEnemyMonType1 +.got_type + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .failed + push hl + dec a + ld hl, Moves + MOVE_TYPE + call GetMoveAttr + ld d, a + pop hl + cp CURSE_TYPE + jr z, .failed + call AnimateCurrentMove + call BattleCommand_SwitchTurn + +.loop + call BattleRandom + maskbits NUM_TYPES + cp UNUSED_TYPES + jr c, .okay + cp UNUSED_TYPES_END + jr c, .loop + cp TYPES_END + jr nc, .loop +.okay + ld [hli], a + ld [hld], a + push hl + ld a, BATTLE_VARS_MOVE_TYPE + call GetBattleVarAddr + push af + push hl + ld a, d + ld [hl], a + call BattleCheckTypeMatchup + pop hl + pop af + ld [hl], a + pop hl + ld a, [wTypeMatchup] + cp EFFECTIVE + jr nc, .loop + call BattleCommand_SwitchTurn + + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + predef GetTypeName + ld hl, TransformedTypeText + jp StdBattleTextbox + +.failed + jp FailMove diff --git a/engine/battle/move_effects/counter.asm b/engine/battle/move_effects/counter.asm new file mode 100644 index 00000000..031c399a --- /dev/null +++ b/engine/battle/move_effects/counter.asm @@ -0,0 +1,59 @@ +BattleCommand_Counter: +; counter + + ld a, 1 + ld [wAttackMissed], a + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + ret z + + ld b, a + callfar GetMoveEffect + ld a, b + cp EFFECT_COUNTER + ret z + + call BattleCommand_ResetTypeMatchup + ld a, [wTypeMatchup] + and a + ret z + + call CheckOpponentWentFirst + ret z + + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + dec a + ld de, wStringBuffer1 + call GetMoveData + + ld a, [wStringBuffer1 + MOVE_POWER] + and a + ret z + + ld a, [wStringBuffer1 + MOVE_TYPE] + cp SPECIAL + ret nc + + ; BUG: Move should fail with all non-damaging battle actions + ld hl, wCurDamage + ld a, [hli] + or [hl] + ret z + + ld a, [hl] + add a + ld [hld], a + ld a, [hl] + adc a + ld [hl], a + jr nc, .capped + ld a, $ff + ld [hli], a + ld [hl], a +.capped + + xor a + ld [wAttackMissed], a + ret diff --git a/engine/battle/move_effects/destiny_bond.asm b/engine/battle/move_effects/destiny_bond.asm new file mode 100644 index 00000000..6a03b9a7 --- /dev/null +++ b/engine/battle/move_effects/destiny_bond.asm @@ -0,0 +1,9 @@ +BattleCommand_DestinyBond: +; destinybond + + ld a, BATTLE_VARS_SUBSTATUS5 + call GetBattleVarAddr + set SUBSTATUS_DESTINY_BOND, [hl] + call AnimateCurrentMove + ld hl, DestinyBondEffectText + jp StdBattleTextbox diff --git a/engine/battle/move_effects/encore.asm b/engine/battle/move_effects/encore.asm new file mode 100644 index 00000000..8ca3595f --- /dev/null +++ b/engine/battle/move_effects/encore.asm @@ -0,0 +1,120 @@ +BattleCommand_Encore: +; encore + + ld hl, wEnemyMonMoves + ld de, wEnemyEncoreCount + ldh a, [hBattleTurn] + and a + jr z, .ok + ld hl, wBattleMonMoves + ld de, wPlayerEncoreCount +.ok + ld a, BATTLE_VARS_LAST_MOVE_OPP + call GetBattleVar + and a + jp z, .failed + cp STRUGGLE + jp z, .failed + cp ENCORE + jp z, .failed + cp MIRROR_MOVE + jp z, .failed + ld b, a + +.got_move + ld a, [hli] + cp b + jr nz, .got_move + + ld bc, wBattleMonPP - wBattleMonMoves - 1 + add hl, bc + ld a, [hl] + and PP_MASK + jp z, .failed + ld a, [wAttackMissed] + and a + jp nz, .failed + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + bit SUBSTATUS_ENCORED, [hl] + jp nz, .failed + set SUBSTATUS_ENCORED, [hl] + call BattleRandom + and $3 + inc a + inc a + inc a + ld [de], a + call CheckOpponentWentFirst + jr nz, .finish_move + ldh a, [hBattleTurn] + and a + jr z, .force_last_enemy_move + + push hl + ld a, [wLastPlayerMove] + ld b, a + ld c, 0 + ld hl, wBattleMonMoves +.find_player_move + ld a, [hli] + cp b + jr z, .got_player_move + inc c + ld a, c + cp NUM_MOVES + jr c, .find_player_move + pop hl + res SUBSTATUS_ENCORED, [hl] + xor a + ld [de], a + jr .failed + +.got_player_move + pop hl + ld a, c + ld [wCurMoveNum], a + ld a, b + ld [wCurPlayerMove], a + dec a + ld de, wPlayerMoveStruct + call GetMoveData + jr .finish_move + +.force_last_enemy_move + push hl + ld a, [wLastEnemyMove] + ld b, a + ld c, 0 + ld hl, wEnemyMonMoves +.find_enemy_move + ld a, [hli] + cp b + jr z, .got_enemy_move + inc c + ld a, c + cp NUM_MOVES + jr c, .find_enemy_move + pop hl + res SUBSTATUS_ENCORED, [hl] + xor a + ld [de], a + jr .failed + +.got_enemy_move + pop hl + ld a, c + ld [wCurEnemyMoveNum], a + ld a, b + ld [wCurEnemyMove], a + dec a + ld de, wEnemyMoveStruct + call GetMoveData + +.finish_move + call AnimateCurrentMove + ld hl, GotAnEncoreText + jp StdBattleTextbox + +.failed + jp PrintDidntAffect2 diff --git a/engine/battle/move_effects/false_swipe.asm b/engine/battle/move_effects/false_swipe.asm new file mode 100644 index 00000000..e2e0c6f1 --- /dev/null +++ b/engine/battle/move_effects/false_swipe.asm @@ -0,0 +1,48 @@ +BattleCommand_FalseSwipe: +; falseswipe + +; Makes sure wCurDamage < MonHP + + ld hl, wEnemyMonHP + ldh a, [hBattleTurn] + and a + jr z, .got_hp + ld hl, wBattleMonHP +.got_hp + ld de, wCurDamage + ld c, 2 + push hl + push de + call CompareBytes + pop de + pop hl + jr c, .done + + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + dec a + ld [de], a + + inc a + jr nz, .okay + dec de + ld a, [de] + dec a + ld [de], a +.okay + + ld a, [wCriticalHit] + cp 2 + jr nz, .carry + xor a + ld [wCriticalHit], a + +.carry + scf + ret + +.done + and a + ret diff --git a/engine/battle/move_effects/heal_bell.asm b/engine/battle/move_effects/heal_bell.asm new file mode 100644 index 00000000..62309f1d --- /dev/null +++ b/engine/battle/move_effects/heal_bell.asm @@ -0,0 +1,34 @@ +BattleCommand_HealBell: +; healbell + + ld a, BATTLE_VARS_SUBSTATUS1 + call GetBattleVarAddr + res SUBSTATUS_NIGHTMARE, [hl] + ld de, wPartyMon1Status + ldh a, [hBattleTurn] + and a + jr z, .got_status + ld de, wOTPartyMon1Status +.got_status + ld a, BATTLE_VARS_STATUS + call GetBattleVarAddr + xor a + ld [hl], a + ld h, d + ld l, e + ld bc, PARTYMON_STRUCT_LENGTH + ld d, PARTY_LENGTH +.loop + ld [hl], a + add hl, bc + dec d + jr nz, .loop + call AnimateCurrentMove + + ld hl, BellChimedText + call StdBattleTextbox + + ldh a, [hBattleTurn] + and a + jp z, CalcPlayerStats + jp CalcEnemyStats diff --git a/engine/battle/move_effects/lock_on.asm b/engine/battle/move_effects/lock_on.asm new file mode 100644 index 00000000..1de3e14b --- /dev/null +++ b/engine/battle/move_effects/lock_on.asm @@ -0,0 +1,21 @@ +BattleCommand_LockOn: +; lockon + + call CheckSubstituteOpp + jr nz, .fail + + ld a, [wAttackMissed] + and a + jr nz, .fail + + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + set SUBSTATUS_LOCK_ON, [hl] + call AnimateCurrentMove + + ld hl, TookAimText + jp StdBattleTextbox + +.fail + call AnimateFailedMove + jp PrintDidntAffect diff --git a/engine/battle/move_effects/pain_split.asm b/engine/battle/move_effects/pain_split.asm new file mode 100644 index 00000000..68d7cfb4 --- /dev/null +++ b/engine/battle/move_effects/pain_split.asm @@ -0,0 +1,92 @@ +BattleCommand_PainSplit: +; painsplit + + ld a, [wAttackMissed] + and a + jp nz, .ButItFailed + call CheckSubstituteOpp + jp nz, .ButItFailed + call AnimateCurrentMove + ld hl, wBattleMonMaxHP + 1 + ld de, wEnemyMonMaxHP + 1 + call .PlayerShareHP + ld a, $1 + ld [wWhichHPBar], a + hlcoord 10, 9 + predef AnimateHPBar + ld hl, wEnemyMonHP + ld a, [hli] + ld [wBuffer4], a + ld a, [hli] + ld [wBuffer3], a + ld a, [hli] + ld [wBuffer2], a + ld a, [hl] + ld [wBuffer1], a + call .EnemyShareHP + xor a + ld [wWhichHPBar], a + call ResetDamage + hlcoord 2, 2 + predef AnimateHPBar + + ld hl, SharedPainText + jp StdBattleTextbox + +.PlayerShareHP: + ld a, [hld] + ld [wBuffer1], a + ld a, [hld] + ld [wBuffer2], a + ld a, [hld] + ld b, a + ld [wBuffer3], a + ld a, [hl] + ld [wBuffer4], a + dec de + dec de + ld a, [de] + dec de + add b + ld [wCurDamage + 1], a + ld b, [hl] + ld a, [de] + adc b + srl a + ld [wCurDamage], a + ld a, [wCurDamage + 1] + rr a + ld [wCurDamage + 1], a + inc hl + inc hl + inc hl + inc de + inc de + inc de + +.EnemyShareHP: + ld c, [hl] + dec hl + ld a, [wCurDamage + 1] + sub c + ld b, [hl] + dec hl + ld a, [wCurDamage] + sbc b + jr nc, .skip + + ld a, [wCurDamage] + ld b, a + ld a, [wCurDamage + 1] + ld c, a +.skip + ld a, c + ld [hld], a + ld [wBuffer5], a + ld a, b + ld [hli], a + ld [wBuffer6], a + ret + +.ButItFailed: + jp PrintDidntAffect2 diff --git a/engine/battle/move_effects/sketch.asm b/engine/battle/move_effects/sketch.asm new file mode 100644 index 00000000..654fb3f5 --- /dev/null +++ b/engine/battle/move_effects/sketch.asm @@ -0,0 +1,117 @@ +BattleCommand_Sketch: +; sketch + + call ClearLastMove +; Don't sketch during a link battle + ld a, [wLinkMode] + and a + jr z, .not_linked + call AnimateFailedMove + jp PrintNothingHappened + +.not_linked +; If the opponent has a substitute up, fail. + call CheckSubstituteOpp + jp nz, .fail +; If the opponent is transformed, fail. + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVarAddr + bit SUBSTATUS_TRANSFORMED, [hl] + jp nz, .fail +; Get the user's moveset in its party struct. +; This move replacement shall be permanent. +; Pointer will be in de. + ld a, MON_MOVES + call UserPartyAttr + ld d, h + ld e, l +; Get the battle move structs. + ld hl, wBattleMonMoves + ldh a, [hBattleTurn] + and a + jr z, .get_last_move + ld hl, wEnemyMonMoves +.get_last_move + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + ld [wNamedObjectIndexBuffer], a + ld b, a +; Fail if move is invalid or is Struggle. + and a + jr z, .fail + cp STRUGGLE + jr z, .fail +; Fail if user already knows that move + ld c, NUM_MOVES +.does_user_already_know_move + ld a, [hli] + cp b + jr z, .fail + dec c + jr nz, .does_user_already_know_move +; Find Sketch in the user's moveset. +; Pointer in hl, and index in c. + dec hl + ld c, NUM_MOVES +.find_sketch + dec c + ld a, [hld] + cp SKETCH + jr nz, .find_sketch + inc hl +; The Sketched move is loaded to that slot. + ld a, b + ld [hl], a +; Copy the base PP from that move. + push bc + push hl + dec a + ld hl, Moves + MOVE_PP + call GetMoveAttr + pop hl + ld bc, wBattleMonPP - wBattleMonMoves + add hl, bc + ld [hl], a + pop bc + + ldh a, [hBattleTurn] + and a + jr z, .user_trainer + ld a, [wBattleMode] + dec a + jr nz, .user_trainer +; wildmon + ld a, [hl] + push bc + ld hl, wWildMonPP + ld b, 0 + add hl, bc + ld [hl], a + ld hl, wWildMonMoves + add hl, bc + pop bc + ld [hl], b + jr .done_copy + +.user_trainer + ld a, [hl] + push af + ld l, c + ld h, 0 + add hl, de + ld a, b + ld [hl], a + pop af + ld de, MON_PP - MON_MOVES + add hl, de + ld [hl], a +.done_copy + call GetMoveName + call AnimateCurrentMove + + ld hl, SketchedText + jp StdBattleTextbox + +.fail + call AnimateFailedMove + jp PrintDidntAffect diff --git a/engine/battle/move_effects/sleep_talk.asm b/engine/battle/move_effects/sleep_talk.asm new file mode 100644 index 00000000..92bff260 --- /dev/null +++ b/engine/battle/move_effects/sleep_talk.asm @@ -0,0 +1,143 @@ +BattleCommand_SleepTalk: +; sleeptalk + + call ClearLastMove + ld a, [wAttackMissed] + and a + jr nz, .fail + ldh a, [hBattleTurn] + and a + ld hl, wBattleMonMoves + 1 + ld a, [wDisabledMove] + ld d, a + jr z, .got_moves + ld hl, wEnemyMonMoves + 1 + ld a, [wEnemyDisabledMove] + ld d, a +.got_moves + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and SLP + jr z, .fail + ld a, [hl] + and a + jr z, .fail + call .safely_check_has_usable_move + jr c, .fail + dec hl +.sample_move + push hl + call BattleRandom + maskbits NUM_MOVES + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + pop hl + and a + jr z, .sample_move + ld e, a + ld a, BATTLE_VARS_MOVE_ANIM + call GetBattleVar + cp e + jr z, .sample_move + ld a, e + cp d + jr z, .sample_move + call .check_two_turn_move + jr z, .sample_move + ld a, BATTLE_VARS_MOVE + call GetBattleVarAddr + ld a, e + ld [hl], a + call CheckUserIsCharging + jr nz, .charging + ld a, [wKickCounter] + push af + call BattleCommand_LowerSub + pop af + ld [wKickCounter], a +.charging + call LoadMoveAnim + call UpdateMoveData + jp ResetTurn + +.fail + call AnimateFailedMove + jp TryPrintButItFailed + +.safely_check_has_usable_move + push hl + push de + push bc + call .check_has_usable_move + pop bc + pop de + pop hl + ret + +.check_has_usable_move + ldh a, [hBattleTurn] + and a + ld a, [wDisabledMove] + jr z, .got_move_2 + + ld a, [wEnemyDisabledMove] +.got_move_2 + ld b, a + ld a, BATTLE_VARS_MOVE + call GetBattleVar + ld c, a + dec hl + ld d, NUM_MOVES +.loop2 + ld a, [hl] + and a + jr z, .carry + + cp c + jr z, .nope + cp b + jr z, .nope + + call .check_two_turn_move + jr nz, .no_carry + +.nope + inc hl + dec d + jr nz, .loop2 + +.carry + scf + ret + +.no_carry + and a + ret + +.check_two_turn_move + push hl + push de + push bc + + ld b, a + callfar GetMoveEffect + ld a, b + + pop bc + pop de + pop hl + + cp EFFECT_SKULL_BASH + ret z + cp EFFECT_RAZOR_WIND + ret z + cp EFFECT_SKY_ATTACK + ret z + cp EFFECT_SOLARBEAM + ret z + cp EFFECT_FLY + ret z + cp EFFECT_BIDE + ret diff --git a/engine/battle/move_effects/snore.asm b/engine/battle/move_effects/snore.asm new file mode 100644 index 00000000..e2432c59 --- /dev/null +++ b/engine/battle/move_effects/snore.asm @@ -0,0 +1,11 @@ +BattleCommand_Snore: +; snore + ld a, BATTLE_VARS_STATUS + call GetBattleVar + and SLP + ret nz + call ResetDamage + ld a, $1 + ld [wAttackMissed], a + call FailMove + jp EndMoveEffect diff --git a/engine/battle/move_effects/spite.asm b/engine/battle/move_effects/spite.asm new file mode 100644 index 00000000..06627268 --- /dev/null +++ b/engine/battle/move_effects/spite.asm @@ -0,0 +1,86 @@ +BattleCommand_Spite: +; spite + + ld a, [wAttackMissed] + and a + jp nz, .failed + ld bc, PARTYMON_STRUCT_LENGTH ; ???? + ld hl, wEnemyMonMoves + ldh a, [hBattleTurn] + and a + jr z, .got_moves + ld hl, wBattleMonMoves +.got_moves + ld a, BATTLE_VARS_LAST_COUNTER_MOVE_OPP + call GetBattleVar + and a + jr z, .failed + cp STRUGGLE + jr z, .failed + ld b, a + ld c, -1 +.loop + inc c + ld a, [hli] + cp b + jr nz, .loop + ld [wNamedObjectIndexBuffer], a + dec hl + ld b, 0 + push bc + ld c, wBattleMonPP - wBattleMonMoves + add hl, bc + pop bc + ld a, [hl] + and PP_MASK + jr z, .failed + push bc + call GetMoveName + ; lose 2-5 PP + call BattleRandom + and %11 + inc a + inc a + ld b, a + ld a, [hl] + and PP_MASK + cp b + jr nc, .deplete_pp + ld b, a +.deplete_pp + ld a, [hl] + sub b + ld [hl], a + push af + ld a, MON_PP + call OpponentPartyAttr + ld d, b + pop af + pop bc + add hl, bc + ld e, a + ld a, BATTLE_VARS_SUBSTATUS5_OPP + call GetBattleVar + bit SUBSTATUS_TRANSFORMED, a + jr nz, .transformed + ldh a, [hBattleTurn] + and a + jr nz, .not_wildmon + ld a, [wBattleMode] + dec a + jr nz, .not_wildmon + ld hl, wWildMonPP + add hl, bc +.not_wildmon + ld [hl], e +.transformed + push de + call AnimateCurrentMove + pop de + ld a, d + ld [wDeciramBuffer], a + ld hl, SpiteEffectText + jp StdBattleTextbox + +.failed + jp PrintDidntAffect2 diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index 8d694eac..46713dfe 100755 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -390,9 +390,9 @@ UltraBall: ; e926 ld [wBattleAnimParam], a ld de, ANIM_THROW_POKE_BALL ld a, e - ld [wcf3e], a + ld [wFXAnimID], a ld a, d - ld [wcf3f], a + ld [wFXAnimID + 1], a xor a ldh [hBattleTurn], a ld [wBuffer2], a @@ -2537,9 +2537,9 @@ Functionf7e7: ; f7e7 (3:77e7) call ReturnToBattle_UseBall ld de, Start ld a, e - ld [wcf3e], a + ld [wFXAnimID], a ld a, d - ld [wcf3f], a + ld [wFXAnimID + 1], a xor a ld [wBattleAnimParam], a ldh [hBattleTurn], a @@ -279,67 +279,83 @@ SECTION "bankc", ROMX SECTION "Effect Commands", ROMX INCLUDE "engine/battle/effect_commands.asm" -BattleCommand_Stab: - dr $34822, $34918 -BattleCheckTypeMatchup:: - dr $34918, $34923 -CheckTypeMatchup:: - dr $34923, $3499e -INCLUDE "engine/battle/ai/switch.asm" - dr $34d01, $3503e - -BattleCommand_LowerSub: - dr $3503e, $3514e -BattleCommand_SwitchTurn: - dr $3514e, $35155 -BattleCommand_RaiseSub: - dr $35155, $353f5 -EndMoveEffect: - dr $353f5, $3553d -EnemyAttackDamage:: - dr $3553d, $3571e -HitSelfInConfusion: - dr $3571e, $35753 -BattleCommand_DamageCalc:: - dr $35753, $35868 -BattleCommand_ConstantDamage:: - dr $35868, $35e3c -FarPlayBattleAnimation: - dr $35e3c, $35e44 -PlayFXAnimID: - dr $35e44, $35e58 -DoEnemyDamage: - dr $35e58, $35eba -DoPlayerDamage: - dr $35eba, $35f7c + UpdateMoveData: - dr $35f7c, $36313 + dr $35f7c, $36201 +Defrost: + dr $36201, $36308 +BattleCommand_StatUp: + dr $36308, $36313 RaiseStat: dr $36313, $364d7 BattleCommand_StatUpMessage: dr $364d7, $3656b BattleCommand_StatUpFailText: - dr $3656b, $366f6 + dr $3656b, $366ce +BattleCommand_RaiseSubNoAnim: + dr $366ce, $366e2 +BattleCommand_LowerSubNoAnim: + dr $366e2, $366f6 CalcPlayerStats: - dr $366f6, $378bd - + dr $366f6, $3671c +CalcEnemyStats: + dr $3671c, $36bcd +CheckOpponentWentFirst: + dr $36bcd, $373dc + +ClearLastMove: + dr $373dc, $37441 +PrintDoesntAffect: + dr $37441, $37447 +PrintNothingHappened: + dr $37447, $3744d +TryPrintButItFailed: + dr $3744d, $37452 +PrintButItFailed: + dr $37452, $37458 +FailMove: + dr $37458, $37464 +PrintDidntAffect: + dr $37464, $3746a +PrintDidntAffect2: + dr $3746a, $3747c +CheckSubstituteOpp: + dr $3747c, $3757a +ResetTurn: + dr $3757a, $378bd ResetFuryCutterCount: dr $378bd, $378f4 CheckOppositeGender: dr $378f4, $37e7d GetUserItem: - dr $37e7d, $37e9b + dr $37e7d, $37e8c +GetOpponentItem: + dr $37e8c, $37e9b GetItemHeldEffect: - dr $37e9b, $37f3e + dr $37e9b, $37ecc +AnimateCurrentMove: + dr $37ecc, $37f01 +LoadMoveAnim: + dr $37f01, $37f0f +LoadAnim: + dr $37f0f, $37f3e CallBattleCore: - dr $37f3e, $37f4b + dr $37f3e, $37f42 +AnimateFailedMove: + dr $37f42, $37f4b BattleCommand_MoveDelay: - dr $37f4b, $37f6c + dr $37f4b, $37f57 +SkipToBattleCommand: + dr $37f57, $37f6c GetMoveAttr: - dr $37f6c, $37f86 + dr $37f6c, $37f78 +GetMoveData: + dr $37f78, $37f86 GetMoveByte: - dr $37f86, $37f99 + dr $37f86, $37f92 +AppearUserLowerSub: + dr $37f92, $37f99 AppearUserRaiseSub: dr $37f99, $37fa0 @@ -355,7 +371,9 @@ INCLUDE "engine/battle/read_trainer_party.asm" SECTION "Battle Core", ROMX dr $3c000, $3c551 FleeMons:: - dr $3c551, $3d39f + dr $3c551, $3c5a4 +GetMoveEffect: + dr $3c5a4, $3d39f EnemySwitch: dr $3d39f, $3d438 @@ -825,7 +843,11 @@ CheckMagikarpLength: MagikarpHouseSign: dr $fbdd6, $fbdf1 HiddenPowerDamage: - dr $fbdf1, $fbf93 + dr $fbdf1, $fbeaa +DoWeatherModifiers: + dr $fbeaa, $fbf2b +DoBadgeTypeBoosts: + dr $fbf2b, $fbf93 SECTION "bank3f", ROMX nop @@ -1698,11 +1698,11 @@ wPlayerEncoreCount:: db ; cb54 wcb55:: ds 1 ; cb55 wPlayerFuryCutterCount:: db ; cb56 wcb57:: ds 1 ; cb57 -wcb58:: ds 1 ; cb58 +wEnemyRolloutCount:: db ; cb58 wEnemyConfuseCount:: db ; cb59 wEnemyToxicCount:: db ; cb5a wEnemyDisableCount:: db ; cb5b -wcb5c:: ds 1 ; cb5c +wEnemyEncoreCount:: db ; cb5c wEnemyPerishCount:: db ; cb5d wEnemyFuryCutterCount:: db ; cb5e wEnemyProtectCount:: db ; cb5f @@ -1761,29 +1761,25 @@ wcb8e:: ds 1 ; cb8e wcb8f:: ds 1 ; cb8f wBattleScriptBufferAddress:: dw ; cb90 wTurnEnded:: db ; cb92 -wcb93:: ds 1 ; cb93 -wcb94:: ds 1 ; cb94 -wcb95:: ds 1 ; cb95 -wcb96:: ds 1 ; cb96 -wcb97:: ds 1 ; cb97 -wcb98:: ds 1 ; cb98 -wcb99:: ds 1 ; cb99 -wcb9a:: ds 1 ; cb9a -wcb9b:: ds 1 ; cb9b -wcb9c:: ds 1 ; cb9c -wcb9d:: ds 1 ; cb9d -wcb9e:: ds 1 ; cb9e -wcb9f:: ds 1 ; cb9f -wcba0:: ds 1 ; cba0 -wcba1:: ds 1 ; cba1 -wcba2:: ds 1 ; cba2 -wcba3:: ds 1 ; cba3 -wcba4:: ds 1 ; cba4 -wcba5:: ds 1 ; cba5 -wcba6:: ds 1 ; cba6 -wcba7:: ds 1 ; cba7 -wcba8:: ds 1 ; cba8 -wcba9:: ds 1 ; cba9 + + ds 1 + +wPlayerStats:: ; cb94 +wPlayerAttack:: dw +wPlayerDefense:: dw +wPlayerSpeed:: dw +wPlayerSpAtk:: dw +wPlayerSpDef:: dw + ds 1 + +wEnemyStats:: ; cb9f +wEnemyAttack:: dw +wEnemyDefense:: dw +wEnemySpeed:: dw +wEnemySpAtk:: dw +wEnemySpDef:: dw + ds 1 + wPlayerAtkLevel:: db ; cbaa wPlayerDefLevel:: db ; cbab wPlayerSpdLevel:: db ; cbac @@ -1803,8 +1799,8 @@ wEnemyEvaLevel:: db ; cbb8 wEnemyTurnsTaken:: db ; cbba wPlayerTurnsTaken:: db ; cbbb wcbbc:: ds 1 ; cbbc -wcbbd:: ds 1 ; cbbd -wcbbe:: ds 1 ; cbbe +wPlayerSubstituteHP:: db ; cbbd +wEnemySubstituteHP:: db ; cbbe wcbbf:: ds 1 ; cbbf wcbc0:: ds 1 ; cbc0 wCurPlayerMove:: ds 1 ; cbc1 @@ -1882,9 +1878,9 @@ wcc05:: ds 1 ; cc05 wcc06:: ds 1 ; cc06 wcc07:: ds 1 ; cc07 wcc08:: ds 1 ; cc08 -wcc09:: ds 1 ; cc09 +wPlayerRageCounter:: db ; cc09 wEnemyRageCounter:: db ; cc0a -wcc0b:: ds 1 ; cc0b +wBeatUpHitAtLeastOnce:: db ; cc0b wcc0c:: ds 1 ; cc0c wcc0d:: ds 1 ; cc0d wPlayerWrapCount:: db ; cc0e @@ -2490,8 +2486,7 @@ wcf3a:: ds 1 wBoxAlignment:: db wcf3c:: ds 1 wcf3d:: ds 1 -wcf3e:: ds 1 -wcf3f:: ds 1 +wFXAnimID:: dw ENDU wcf40:: ds 1 ; cf40 @@ -2864,8 +2859,8 @@ wBaseDexNo:: ; d120 wCurBaseData:: ; d120 wd120:: ds 1 ; d120 wd121:: ds 1 ; d121 -wd122:: ds 1 ; d122 -wd123:: ds 1 ; d123 +wBaseAttack:: db ; d122 +wBaseDefense:: db ; d123 wd124:: ds 1 ; d124 wd125:: ds 1 ; d125 wd126:: ds 1 ; d126 |